|
|
|
@ -15,14 +15,16 @@ from rest_framework.permissions import IsAuthenticated |
|
|
|
from rest_framework.renderers import JSONRenderer |
|
|
|
from rest_framework.renderers import JSONRenderer |
|
|
|
from rest_framework.response import Response |
|
|
|
from rest_framework.response import Response |
|
|
|
from rest_framework.views import APIView |
|
|
|
from rest_framework.views import APIView |
|
|
|
from django.db.models import Q, Count |
|
|
|
from django.db.models import Q, Count, F |
|
|
|
import jwt |
|
|
|
import jwt |
|
|
|
from django.conf import settings |
|
|
|
from django.conf import settings |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
from django.db.models.functions import Cast |
|
|
|
|
|
|
|
from django.db.models.fields import DateField |
|
|
|
from access.serializers import UserProgressSearchSerializer |
|
|
|
from access.serializers import UserProgressSearchSerializer |
|
|
|
from courses.models import Course, Lesson |
|
|
|
from courses.models import Course, Lesson |
|
|
|
from progress.models import ProgressLesson, Progress |
|
|
|
from progress.models import ProgressLesson, Progress |
|
|
|
from progress.serializers import ProgressAnalyticSerializer, ProgressLessonSerializer, ProgressSerializer, \ |
|
|
|
from progress.serializers import ProgressAnalyticSerializer, ProgressLessonSerializer, \ |
|
|
|
SecureProgressSerializer |
|
|
|
SecureProgressSerializer |
|
|
|
from courses.api import CourseProgressApi, CourseParamsApi |
|
|
|
from courses.api import CourseProgressApi, CourseParamsApi |
|
|
|
from progress.tasks import add_next_lesson |
|
|
|
from progress.tasks import add_next_lesson |
|
|
|
@ -65,27 +67,134 @@ class CourseProgressDynamicView(APIView): |
|
|
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
@staticmethod |
|
|
|
def get(request): |
|
|
|
def get(request): |
|
|
|
course_token = request.GET.get('course_token', None) |
|
|
|
course_token = request.GET.get('course_token', '') |
|
|
|
|
|
|
|
teacher_email = request.GET.get('teacher_email', '').lower() |
|
|
|
from_date = int(request.GET.get('from', '7')) |
|
|
|
from_date = int(request.GET.get('from', '7')) |
|
|
|
to_date = int(request.GET.get('to', '0')) |
|
|
|
to_date = int(request.GET.get('to', '0')) |
|
|
|
|
|
|
|
only_hw = request.GET.get('only_hw', 'yes') == 'yes' |
|
|
|
|
|
|
|
|
|
|
|
if request.user.is_authenticated() and request.user.is_staff: |
|
|
|
if request.user.is_authenticated() and request.user.is_staff: |
|
|
|
progresses = ProgressLesson.objects.filter(status='done') |
|
|
|
progresses = ProgressLesson.objects.all() |
|
|
|
if not course_token is None: |
|
|
|
waiters = ProgressLesson.objects.filter(status='wait') |
|
|
|
try: |
|
|
|
|
|
|
|
|
|
|
|
if only_hw: |
|
|
|
|
|
|
|
progresses = progresses.filter(checker=F('progress__teacher')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if not course_token is '': |
|
|
|
progresses = progresses.filter(progress__course_token=course_token) |
|
|
|
progresses = progresses.filter(progress__course_token=course_token) |
|
|
|
except ProgressLesson.DoesNotExist: |
|
|
|
|
|
|
|
return Response('incorrect course token', status=404) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
progresses = progresses.filter(finish_date__gt=timezone.now() - relativedelta(days=from_date)) |
|
|
|
if not teacher_email is '': |
|
|
|
progresses = progresses.filter(finish_date__lt=timezone.now() - relativedelta(days=to_date)) |
|
|
|
waiters = waiters.filter(checker__email=teacher_email) |
|
|
|
progresses = progresses.order_by('finish_date') |
|
|
|
progresses = progresses.filter(checker__email=teacher_email) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res = {} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
progresses_finish = progresses.filter(finish_date__gt=timezone.now() - relativedelta(days=from_date)) |
|
|
|
|
|
|
|
progresses_finish = progresses_finish.filter(finish_date__lt=timezone.now() - relativedelta(days=to_date)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
progresses_start = progresses.filter(start_date__gt=timezone.now() - relativedelta(days=from_date)) |
|
|
|
|
|
|
|
progresses_start = progresses_start.filter(start_date__lt=timezone.now() - relativedelta(days=to_date)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
progresses_finish = progresses_finish.annotate(name=Cast('finish_date', DateField())) \ |
|
|
|
|
|
|
|
.values('name') \ |
|
|
|
|
|
|
|
.annotate(value=Count('id')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
progresses_start = progresses_start.annotate(name=Cast('start_date', DateField())) \ |
|
|
|
|
|
|
|
.values('name') \ |
|
|
|
|
|
|
|
.annotate(value=Count('id')) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
progresses_finish = progresses_finish.order_by('name') |
|
|
|
|
|
|
|
progresses_start = progresses_start.order_by('name') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
res['finish'] = progresses_finish |
|
|
|
|
|
|
|
res['start'] = progresses_start |
|
|
|
|
|
|
|
res['in_progress'] = waiters.count() |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Response(res, status=200) |
|
|
|
|
|
|
|
return Response('Доступно только персоналу', status=403) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class CourseProgressTableView(APIView): |
|
|
|
|
|
|
|
renderer_classes = (JSONRenderer,) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
|
|
|
|
def get(request): |
|
|
|
|
|
|
|
from_date = request.GET.get('from', None) |
|
|
|
|
|
|
|
to_date = request.GET.get('to', None) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if request.user.is_authenticated() and request.user.is_staff: |
|
|
|
|
|
|
|
progresses = ProgressLesson.objects.filter(checker=F('progress__teacher'), progress__only_watch=False) \ |
|
|
|
|
|
|
|
.exclude(status='done') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if from_date is not None: |
|
|
|
|
|
|
|
date = timezone.now() - relativedelta(days=int(from_date)) |
|
|
|
|
|
|
|
progresses = progresses.filter(progress__user__useractivity__last_request__gt=date) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if to_date is not None: |
|
|
|
|
|
|
|
date = timezone.now() - relativedelta(days=int(to_date)) |
|
|
|
|
|
|
|
progresses = progresses.filter(progress__user__useractivity__last_request__lt=date) |
|
|
|
|
|
|
|
|
|
|
|
res = {} |
|
|
|
res = {} |
|
|
|
progresses = progresses.extra({'finish_date_day': "date(finish_date)"})\ |
|
|
|
progresses = progresses.values('progress__course_token', 'lesson_token').annotate(count=Count('id')) |
|
|
|
.values('progress__course_token', 'finish_date_day')\ |
|
|
|
course_tokens = progresses.values('progress__course_token').distinct() |
|
|
|
.annotate(total=Count('progress')) |
|
|
|
res['val'] = [] |
|
|
|
#TODO Доделать |
|
|
|
res['max_length'] = 0 |
|
|
|
|
|
|
|
for course_token in course_tokens: |
|
|
|
|
|
|
|
ct = course_token['progress__course_token'] |
|
|
|
|
|
|
|
api = CourseParamsApi(ct) |
|
|
|
|
|
|
|
course_title = api.get_slug_and_title()['title'] |
|
|
|
|
|
|
|
course_length = api.get_length() |
|
|
|
|
|
|
|
res['max_length'] = course_length if course_length > res['max_length'] else res['max_length'] |
|
|
|
|
|
|
|
f_progresses = progresses.filter(progress__course_token=ct) |
|
|
|
|
|
|
|
res_elem = { |
|
|
|
|
|
|
|
"course_title": course_title, |
|
|
|
|
|
|
|
"course_token": course_token['progress__course_token'], |
|
|
|
|
|
|
|
'stat': [0 for _i in range(course_length)], |
|
|
|
|
|
|
|
"sum": 0 |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
res['val'].append(res_elem) |
|
|
|
|
|
|
|
for i in f_progresses: |
|
|
|
|
|
|
|
topic = api.get_topic_by_lesson(i['lesson_token']) |
|
|
|
|
|
|
|
if topic is not None: |
|
|
|
|
|
|
|
res_elem['stat'][topic['idx']] += i["count"] |
|
|
|
|
|
|
|
res_elem['sum'] += i["count"] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Response(res, status=200) |
|
|
|
|
|
|
|
return Response('Доступно только персоналу', status=403) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ProgressTableDetailView(APIView): |
|
|
|
|
|
|
|
renderer_classes = (JSONRenderer,) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
|
|
|
|
def get(request): |
|
|
|
|
|
|
|
course_token = request.GET.get('course_token', None) |
|
|
|
|
|
|
|
topic_idx = request.GET.get('topic_idx', None) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if course_token is None: |
|
|
|
|
|
|
|
return Response('Должен быть передан токен курса', 400) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if request.user.is_authenticated() and request.user.is_staff: |
|
|
|
|
|
|
|
progresses = ProgressLesson.objects.filter( |
|
|
|
|
|
|
|
checker=F('progress__teacher'), |
|
|
|
|
|
|
|
progress__only_watch=False, |
|
|
|
|
|
|
|
progress__course_token=course_token, |
|
|
|
|
|
|
|
) \ |
|
|
|
|
|
|
|
.exclude(status='done') |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api = CourseParamsApi(course_token) |
|
|
|
|
|
|
|
res = [] |
|
|
|
|
|
|
|
for progress in progresses: |
|
|
|
|
|
|
|
topic = api.get_topic_by_lesson(progress.lesson_token) |
|
|
|
|
|
|
|
if topic_idx is not None and not int(topic_idx)-1 == topic['idx']: |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
res.append({ |
|
|
|
|
|
|
|
'email': progress.progress.user.email, |
|
|
|
|
|
|
|
'name': progress.progress.user.get_full_name(), |
|
|
|
|
|
|
|
'status': progress.status, |
|
|
|
|
|
|
|
'last_request': progress.progress.user.useractivity.last_request, |
|
|
|
|
|
|
|
'topic_title': topic['title'], |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
|
|
return Response(res, status=200) |
|
|
|
return Response(res, status=200) |
|
|
|
return Response('Доступно только персоналу', status=403) |
|
|
|
return Response('Доступно только персоналу', status=403) |
|
|
|
@ -337,7 +446,7 @@ class ChangeTeacherView(APIView): |
|
|
|
except get_user_model().DoesNotExist: |
|
|
|
except get_user_model().DoesNotExist: |
|
|
|
return Response("Нет пользователя c таким email", status=404) |
|
|
|
return Response("Нет пользователя c таким email", status=404) |
|
|
|
p.teacher = teacher |
|
|
|
p.teacher = teacher |
|
|
|
p.progresslesson_set.filter(status=ProgressLesson.STATUSES.wait).update(checker=teacher) |
|
|
|
p.progresslesson_set.exclude(status=ProgressLesson.STATUSES.done).update(checker=teacher) |
|
|
|
p.save() |
|
|
|
p.save() |
|
|
|
except Progress.DoesNotExist: |
|
|
|
except Progress.DoesNotExist: |
|
|
|
return Response("не найден прогресс по заданному id", status=404) |
|
|
|
return Response("не найден прогресс по заданному id", status=404) |
|
|
|
|