diff --git a/courses/serializers.py b/courses/serializers.py index 3309f1e..3dcf85b 100644 --- a/courses/serializers.py +++ b/courses/serializers.py @@ -19,7 +19,7 @@ class MiniLessonSerializer(serializers.ModelSerializer): class Meta: model = Lesson - fields = ('title', 'free', 'token') + fields = ('title', 'free', 'token', 'is_hm') class LessonSerializer(MiniLessonSerializer): diff --git a/lms/settings.py b/lms/settings.py index 4c8081b..2a4e59e 100644 --- a/lms/settings.py +++ b/lms/settings.py @@ -68,7 +68,7 @@ DATABASES = { SESSION_ENGINE = 'redis_sessions.session' CELERY_EMAIL_CHUNK_SIZE = 1 -DATA_UPLOAD_MAX_MEMORY_SIZE = 12621440 +DATA_UPLOAD_MAX_MEMORY_SIZE = 300000000 CACHES = { 'default': env.cache(), diff --git a/progress/migrations/0008_auto_20180227_1803.py b/progress/migrations/0008_auto_20180227_1803.py new file mode 100644 index 0000000..b1cd9b6 --- /dev/null +++ b/progress/migrations/0008_auto_20180227_1803.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2018-02-27 18:03 +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('progress', '0007_progresslesson_last_update'), + ] + + operations = [ + migrations.RemoveField( + model_name='progress', + name='hidden_lessons', + ), + migrations.AddField( + model_name='progress', + name='only_watch', + field=models.BooleanField(default=False, verbose_name='Только просмотр'), + ), + ] diff --git a/progress/models.py b/progress/models.py index 12a4274..2a6e5dc 100644 --- a/progress/models.py +++ b/progress/models.py @@ -7,16 +7,12 @@ from lms.tools import get_empty_list class Progress(models.Model): - hidden_lessons = ArrayField( - models.UUIDField(verbose_name="Токен урока", unique=True, editable=False), - default=get_empty_list, - verbose_name='Список скрытых уроков', - ) teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию", related_name='teacher_progress') user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент') course_token = models.UUIDField(verbose_name="Токен курса", editable=False) is_finish = models.BooleanField(verbose_name="Окончен ли курс", default=False) + only_watch = models.BooleanField(verbose_name="Только просмотр", default=False) def progress_status(self, sorted_token_list): """ diff --git a/progress/serializers.py b/progress/serializers.py index e156bd3..ea27df1 100644 --- a/progress/serializers.py +++ b/progress/serializers.py @@ -8,7 +8,7 @@ class ProgressSerializer(serializers.ModelSerializer): class Meta: model = Progress - fields = ('lessons', 'course_token') + fields = ('lessons', 'course_token', 'only_watch') @staticmethod def get_lessons(self): diff --git a/progress/urls.py b/progress/urls.py index b78ac8f..44b7bd1 100644 --- a/progress/urls.py +++ b/progress/urls.py @@ -7,4 +7,5 @@ urlpatterns = [ url(r'student/$', views.StudentUpdateProgress.as_view()), url(r'teacher/$', views.TeacherUpdateProgress.as_view()), url(r'set-progress/$', views.SetProgress.as_view()), + url(r'get_hw_pay/$', views.get_teachers_pay), ] \ No newline at end of file diff --git a/progress/views.py b/progress/views.py index f744103..6536517 100644 --- a/progress/views.py +++ b/progress/views.py @@ -3,7 +3,7 @@ import datetime from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError -from django.http import HttpResponse +from django.http import HttpResponse, HttpResponseForbidden from rest_framework.permissions import IsAuthenticated from rest_framework.renderers import JSONRenderer from rest_framework.response import Response @@ -13,7 +13,7 @@ from django.db.models import Q from courses.models import Course from progress.models import ProgressLesson, Progress from progress.serializers import ProgressAnalyticSerializer, ProgressLessonSerializer, ProgressSerializer -from courses.api import CourseProgressApi +from courses.api import CourseProgressApi, CourseParamsApi from progress.tasks import add_next_lesson @@ -23,18 +23,25 @@ class StudentWorkView(APIView): @staticmethod def get(request, teacher_token): client_status = request.GET.get('status', 'in_progress') - client_max_body = 50 - last_id = request.GET.get('last_id', 0) - server_status = Q(status='fail') if \ - client_status == 'not_done' else Q(status='wait') if client_status == 'in_progress' else Q(status='done') if request.user.is_authenticated() and request.user.groups.filter(name__in=['teachers', 'admin']).exists(): try: - progress_lessons = ProgressLesson.objects.filter( - ~Q(progress__user__out_key=teacher_token), - server_status, - checker__out_key=teacher_token, - id__gt=last_id - )[:client_max_body] + if client_status == 'done': + date_from = datetime.datetime.now() - datetime.timedelta(days=7) + progress_lessons = ProgressLesson.objects.filter( + ~Q(progress__user__out_key=teacher_token), + ~Q(comment_tokens__len=0), + status='done', + checker__out_key=teacher_token, + finish_date__gte=date_from, + ).order_by('finish_date') + + else: + server_status = Q(status='fail') if client_status == 'not_done' else Q(status='wait') + progress_lessons = ProgressLesson.objects.filter( + ~Q(progress__user__out_key=teacher_token), + server_status, + checker__out_key=teacher_token, + ).order_by('-last_update') return Response([ProgressLessonSerializer(i).data for i in progress_lessons], status=200) except ValidationError: return Response("Bad request", status=400) @@ -348,3 +355,43 @@ class SetProgress(APIView): else: return Response("Эта функция доступна только сотрудникам персонала", status=403) + + +def get_teachers_pay(request): + if not request.user.is_authenticated and (request.user.groups.filter(name="support") or request.user.is_superuser): + return HttpResponseForbidden() + + date_from = request.GET.get('from', None) + date_to = request.GET.get('to', None) + email = request.GET.get('email', None) + + file_name = "teacher_pay_%s" % email + file_name = file_name + "__from_%s" % date_from if date_from else file_name + file_name = file_name + "__to_%s" % date_to if date_to else file_name + + progress_lessons = ProgressLesson.objects.filter( + ~Q(comment_tokens__len=0), + checker__email=email, + status='done', + ) + + progress_lessons = progress_lessons.filter(finish_date__lt=date_to) if date_to else progress_lessons + progress_lessons = progress_lessons.filter(finish_date__gte=date_from) if date_from else progress_lessons + + response = HttpResponse(content_type='text/csv') + response['Content-Disposition'] = 'attachment; filename="%s.csv"' % file_name + + writer = csv.writer(response) + writer.writerow(['Почта студента', 'Имя студента', 'Курс', 'Дата', 'Время',]) + + for i in progress_lessons.order_by('-finish_date'): + course_api = CourseParamsApi(i.progress.course_token) + writer.writerow([ + i.progress.user.email, + i.progress.user.get_full_name(), + course_api.get_slug_and_title()['title'], + i.finish_date.date(), + i.finish_date.time(), + ]) + + return response diff --git a/requirements.txt b/requirements.txt index 57e3a0d..b292272 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,6 +15,7 @@ psycopg2==2.7.3.1 raven==6.2.1 requests==2.18.4 Unidecode==0.4.21 +PyJWT==1.5.3 # amqp==2.2.2 # Babel==2.5.1 diff --git a/storage/api.py b/storage/api.py index 2b80a8b..1afcf62 100644 --- a/storage/api.py +++ b/storage/api.py @@ -1,11 +1,11 @@ from storage.models import Comment, File -def upload_file(original=None, name=None, base64=None, **_kwargs) -> File: +def upload_file(ext=None, original=None, name=None, base64=None, **_kwargs) -> File: if original: new_file = File.objects.create(original=original) else: - new_file = File.objects.upload_as_base64(base64) + new_file = File.objects.upload_as_base64(base64, ext) if name: new_file.name = name diff --git a/storage/models.py b/storage/models.py index 9946f71..8e1b9d7 100755 --- a/storage/models.py +++ b/storage/models.py @@ -1,4 +1,5 @@ # encoding=utf-8 + import base64 import uuid @@ -8,11 +9,10 @@ from django.db import models class FileManager(models.Manager): - def upload_as_base64(self, file_base64): + def upload_as_base64(self, file_base64, ext): if "data:" in file_base64: my_str = file_base64[file_base64.index(";base64,")+8:] - content_type = file_base64[:file_base64.index(";base64,")].split('/')[1] - file_source = ContentFile(base64.b64decode(my_str), name='time.' + content_type) + file_source = ContentFile(base64.b64decode(my_str), name='time.' + ext) file = self.create(original=file_source) return file raise ValueError()