Merge branch 'dev' into feature/test_course

feature/fix_generate_pass
Dmitriy Shesterkin 8 years ago
commit b7b0a6fac6
  1. 2
      courses/serializers.py
  2. 2
      lms/settings.py
  3. 24
      progress/migrations/0008_auto_20180227_1803.py
  4. 6
      progress/models.py
  5. 2
      progress/serializers.py
  6. 1
      progress/urls.py
  7. 71
      progress/views.py
  8. 1
      requirements.txt
  9. 4
      storage/api.py
  10. 6
      storage/models.py

@ -19,7 +19,7 @@ class MiniLessonSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Lesson model = Lesson
fields = ('title', 'free', 'token') fields = ('title', 'free', 'token', 'is_hm')
class LessonSerializer(MiniLessonSerializer): class LessonSerializer(MiniLessonSerializer):

@ -68,7 +68,7 @@ DATABASES = {
SESSION_ENGINE = 'redis_sessions.session' SESSION_ENGINE = 'redis_sessions.session'
CELERY_EMAIL_CHUNK_SIZE = 1 CELERY_EMAIL_CHUNK_SIZE = 1
DATA_UPLOAD_MAX_MEMORY_SIZE = 12621440 DATA_UPLOAD_MAX_MEMORY_SIZE = 300000000
CACHES = { CACHES = {
'default': env.cache(), 'default': env.cache(),

@ -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='Только просмотр'),
),
]

@ -7,16 +7,12 @@ from lms.tools import get_empty_list
class Progress(models.Model): 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="Преподователь по умолчанию", teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию",
related_name='teacher_progress') related_name='teacher_progress')
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент') user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент')
course_token = models.UUIDField(verbose_name="Токен курса", editable=False) course_token = models.UUIDField(verbose_name="Токен курса", editable=False)
is_finish = models.BooleanField(verbose_name="Окончен ли курс", default=False) is_finish = models.BooleanField(verbose_name="Окончен ли курс", default=False)
only_watch = models.BooleanField(verbose_name="Только просмотр", default=False)
def progress_status(self, sorted_token_list): def progress_status(self, sorted_token_list):
""" """

@ -8,7 +8,7 @@ class ProgressSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Progress model = Progress
fields = ('lessons', 'course_token') fields = ('lessons', 'course_token', 'only_watch')
@staticmethod @staticmethod
def get_lessons(self): def get_lessons(self):

@ -7,4 +7,5 @@ urlpatterns = [
url(r'student/$', views.StudentUpdateProgress.as_view()), url(r'student/$', views.StudentUpdateProgress.as_view()),
url(r'teacher/$', views.TeacherUpdateProgress.as_view()), url(r'teacher/$', views.TeacherUpdateProgress.as_view()),
url(r'set-progress/$', views.SetProgress.as_view()), url(r'set-progress/$', views.SetProgress.as_view()),
url(r'get_hw_pay/$', views.get_teachers_pay),
] ]

@ -3,7 +3,7 @@ import datetime
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import ValidationError 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.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
@ -13,7 +13,7 @@ from django.db.models import Q
from courses.models import Course from courses.models import Course
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, ProgressSerializer
from courses.api import CourseProgressApi from courses.api import CourseProgressApi, CourseParamsApi
from progress.tasks import add_next_lesson from progress.tasks import add_next_lesson
@ -23,18 +23,25 @@ class StudentWorkView(APIView):
@staticmethod @staticmethod
def get(request, teacher_token): def get(request, teacher_token):
client_status = request.GET.get('status', 'in_progress') 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(): if request.user.is_authenticated() and request.user.groups.filter(name__in=['teachers', 'admin']).exists():
try: try:
progress_lessons = ProgressLesson.objects.filter( if client_status == 'done':
~Q(progress__user__out_key=teacher_token), date_from = datetime.datetime.now() - datetime.timedelta(days=7)
server_status, progress_lessons = ProgressLesson.objects.filter(
checker__out_key=teacher_token, ~Q(progress__user__out_key=teacher_token),
id__gt=last_id ~Q(comment_tokens__len=0),
)[:client_max_body] 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) return Response([ProgressLessonSerializer(i).data for i in progress_lessons], status=200)
except ValidationError: except ValidationError:
return Response("Bad request", status=400) return Response("Bad request", status=400)
@ -348,3 +355,43 @@ class SetProgress(APIView):
else: else:
return Response("Эта функция доступна только сотрудникам персонала", status=403) 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

@ -15,6 +15,7 @@ psycopg2==2.7.3.1
raven==6.2.1 raven==6.2.1
requests==2.18.4 requests==2.18.4
Unidecode==0.4.21 Unidecode==0.4.21
PyJWT==1.5.3
# amqp==2.2.2 # amqp==2.2.2
# Babel==2.5.1 # Babel==2.5.1

@ -1,11 +1,11 @@
from storage.models import Comment, File 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: if original:
new_file = File.objects.create(original=original) new_file = File.objects.create(original=original)
else: else:
new_file = File.objects.upload_as_base64(base64) new_file = File.objects.upload_as_base64(base64, ext)
if name: if name:
new_file.name = name new_file.name = name

@ -1,4 +1,5 @@
# encoding=utf-8 # encoding=utf-8
import base64 import base64
import uuid import uuid
@ -8,11 +9,10 @@ from django.db import models
class FileManager(models.Manager): class FileManager(models.Manager):
def upload_as_base64(self, file_base64): def upload_as_base64(self, file_base64, ext):
if "data:" in file_base64: if "data:" in file_base64:
my_str = file_base64[file_base64.index(";base64,")+8:] 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.' + ext)
file_source = ContentFile(base64.b64decode(my_str), name='time.' + content_type)
file = self.create(original=file_source) file = self.create(original=file_source)
return file return file
raise ValueError() raise ValueError()

Loading…
Cancel
Save