You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1699 lines
70 KiB
1699 lines
70 KiB
# coding=utf-8
|
|
from __future__ import unicode_literals
|
|
import datetime
|
|
import os
|
|
|
|
from django.conf import settings
|
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.db import models
|
|
from django.db.models import Q
|
|
|
|
from access.models import User
|
|
from courses.models import CourseTheme, Lesson, Homework, Exam, Achievements, Course, CourseMap, \
|
|
AchievementsMap, \
|
|
Diploma
|
|
from courses.templates import search_in_collection, STATUS_COLLECTION, comment_fabric, BUTTON_TYPE
|
|
from management.models import Comment
|
|
from lms.settings import TEACHER, DOMAIN, BASE_DIR
|
|
from lms.tools import out_date_format, gen_write
|
|
from finance.models import Bill
|
|
import operator
|
|
|
|
|
|
def get_active_tj_count(teacher):
|
|
# Получить количество активных журналов по этому курсу
|
|
return HomeworkJ.objects.filter(teacher=teacher, f_date=None, success=False).exclude(date=None).count()
|
|
|
|
|
|
class TeacherJ(models.Model):
|
|
# Журнал преподавания
|
|
TJSTATUS = (
|
|
('O', u'Пустой'),
|
|
('W', u'В работе'),
|
|
('F', u'Завершен')
|
|
)
|
|
status = models.CharField(verbose_name=u'Статус', choices=TJSTATUS, default='O', max_length=1)
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', related_name=u'teacherJ_student', null=True, blank=True)
|
|
full = models.BooleanField(verbose_name=u'Журнал создан', default=False)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс')
|
|
homework = models.ForeignKey(Homework, verbose_name=u'ДЗ', blank=True, null=True)
|
|
lesson = models.ForeignKey(Lesson, verbose_name=u'Урок', blank=True, null=True)
|
|
progress = models.IntegerField(verbose_name=u'Прогресс', default=0)
|
|
current_token = models.CharField(verbose_name=u'Текущий ключ', blank=True, default='', max_length=100)
|
|
teacher = models.ForeignKey(User, verbose_name=u'Преподаватель', related_name=u'teacherJ_teacher', blank=True,
|
|
null=True)
|
|
start_date = models.DateTimeField(verbose_name=u'Дата начала', blank=True, null=True)
|
|
opens = models.ManyToManyField(CourseMap, verbose_name=u'Насильные открытия', blank=True, editable=False,
|
|
related_name='map_opens')
|
|
waiting = models.ManyToManyField(CourseMap, verbose_name=u'Доп изучения', blank=True,
|
|
related_name='map_waiting')
|
|
|
|
def __str__(self):
|
|
return '%s %s %s' % (self.teacher, self.student, self.course)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s %s' % (self.teacher, self.student, self.course)
|
|
|
|
def append_waiting(self, point):
|
|
obj = point.get_obj()
|
|
cj = CourseThemeJ.objects.get(student=self.student, material=obj.theme)
|
|
result = False
|
|
if cj.get_status_flag() == 'F':
|
|
result = True
|
|
for i in self.opens.all():
|
|
if i.token > point.token:
|
|
result = False
|
|
|
|
if result:
|
|
self.waiting.add(point)
|
|
|
|
def get_current_ht(self):
|
|
# Получить текущую попытку ДЗ
|
|
return HomeworkTry.objects.filter(parent__parent__parent=self, success=False, f_date=None).last() \
|
|
if HomeworkTry.objects.filter(parent__parent__parent=self, success=False, f_date=None).exists() \
|
|
else None
|
|
|
|
def get_last_hw(self):
|
|
return HomeworkJ.objects.filter(parent__parent=self, success=False, f_date=None).last() if HomeworkJ.objects.filter(parent__parentt=self, success=False, f_date=None).exists() else None
|
|
|
|
def reload_progress(self, _with_save=True):
|
|
result = 0
|
|
# 1) Получение количества уроков + экзамен
|
|
all_lessons = Lesson.objects.filter(course=self.course).count() + \
|
|
Homework.objects.filter(course=self.course).count() + \
|
|
Exam.objects.filter(course=self.course).count()
|
|
finish_lessons = LessonJ.objects.filter(parent__parent=self, success=True, student=self.student).count() + \
|
|
HomeworkJ.objects.filter(parent__parent=self, success=True, student=self.student).count() + \
|
|
ExamJ.objects.filter(parent__parent=self, success=True, student=self.student).count()
|
|
# 2) Разделить на количество пройденых уроков
|
|
if all_lessons and finish_lessons:
|
|
result = int(float(100 / (float(all_lessons) / float(finish_lessons))))
|
|
self.progress = result
|
|
if _with_save:
|
|
self.save()
|
|
|
|
def get_status(self):
|
|
# Проверка
|
|
return ''
|
|
|
|
def get_empty_head_face(self):
|
|
return {
|
|
'title': self.course.get_title(),
|
|
'mid': self.course.id,
|
|
'slug': self.course.slug,
|
|
'id': None,
|
|
'material': self.course,
|
|
'progress': 0,
|
|
'level': self.course.get_level(),
|
|
'lessons': self.course.lessons_length(),
|
|
'img': self.course.get_image(),
|
|
'big_img': self.course.get_big_image(),
|
|
'mobil_img': self.course.get_mobile_big_image(),
|
|
'skills': self.course.get_skills(),
|
|
'page': self.course.page,
|
|
'course_id': self.course.id
|
|
}
|
|
|
|
def get_head_face(self):
|
|
if self.start_date and self.student:
|
|
by = Bill.objects.filter(service__course=self.course, status='F', user=self.student)
|
|
flow_status = None
|
|
start_flow = None
|
|
if by.exists():
|
|
if by[0].flow:
|
|
flow_status = by[0].flow.get_status()
|
|
start_flow = by[0].flow.start_flow
|
|
return {
|
|
'title': self.course.get_title(),
|
|
'teacher': self.teacher,
|
|
'mid': self.course.id,
|
|
'slug': self.course.slug,
|
|
'id': self.id,
|
|
'material': self.course,
|
|
'progress': self.progress,
|
|
'level': self.course.get_level(),
|
|
'lessons': self.course.lessons_length(),
|
|
'img': self.course.get_image(),
|
|
'big_img': self.course.get_big_image(),
|
|
'mobil_img': self.course.get_mobile_big_image(),
|
|
'skills': self.course.get_skills(),
|
|
'page': self.course.page,
|
|
'course_id': self.course.id,
|
|
'by': by.exists(),
|
|
'by_type': '',
|
|
'by_flow': flow_status,
|
|
'by_start_flow': start_flow
|
|
}
|
|
else:
|
|
return self.get_empty_head_face()
|
|
|
|
def get_empty_face(self, user):
|
|
# Получить темы
|
|
return {
|
|
'head': self.get_empty_head_face(),
|
|
'student': self.student,
|
|
'themes': (theme.get_empty_face(user) for theme in CourseThemeJ.objects.filter(parent=self))
|
|
}
|
|
|
|
def get_face(self, user):
|
|
if not self.full:
|
|
check_journal(self, from_console=True)
|
|
self.full = True
|
|
self.save()
|
|
if self.start_date and self.student:
|
|
return {
|
|
'head': self.get_head_face(),
|
|
'student': self.student,
|
|
'themes': (theme.get_face(user) for theme in CourseThemeJ.objects.filter(parent=self)),
|
|
'length': CourseThemeJ.objects.filter(parent=self).count()
|
|
}
|
|
else:
|
|
return self.get_empty_face(user)
|
|
|
|
def get_low_teacher(self):
|
|
# Получение наименее загруженного препода
|
|
t = {}
|
|
for i in self.course.teachers.exclude(Q(email=TEACHER)|Q(deactivate=True)):
|
|
t[i] = get_active_tj_count(i)
|
|
for key, value in sorted(t.items(), key=operator.itemgetter(1)):
|
|
return key
|
|
|
|
def teacher_to_set(self):
|
|
if self.teacher:
|
|
return self.teacher
|
|
else:
|
|
if self.student and self.student.in_role != 'U':
|
|
return User.objects.get(email=TEACHER)
|
|
teachers = self.course.teachers.all()
|
|
if len(teachers) == 1:
|
|
return teachers.first()
|
|
else:
|
|
return self.get_low_teacher()
|
|
|
|
def get_teacher(self):
|
|
# Получение преподавателя для студента по курсу
|
|
return self.teacher
|
|
|
|
def reload_status(self):
|
|
status = self.status
|
|
if self.teacher:
|
|
status = 'W'
|
|
|
|
if Exam.objects.filter(course=self.course).exists() and ExamJ.objects.filter(success=True, parent__parent=self).exists():
|
|
status = 'F'
|
|
|
|
return status
|
|
|
|
def save(self, *args, **kwargs):
|
|
'''
|
|
if self.current_tch != self.teacher:
|
|
hw = self.get_current_ht()
|
|
if hw:
|
|
if hw.parent.teacher != self.teacher:
|
|
hw.parent.teacher = self.teacher
|
|
hw.parent.save()
|
|
|
|
if hw.teacher != self.teacher:
|
|
hw.new_teach = self.teacher
|
|
hw.save()
|
|
|
|
else:
|
|
hw = self.get_last_hw()
|
|
if hw:
|
|
hw.teacher = self.teacher
|
|
hw.save()
|
|
|
|
self.current_tch = self.teacher
|
|
'''
|
|
self.reload_progress(_with_save=False)
|
|
|
|
status = self.reload_status()
|
|
if self.status != status:
|
|
self.status = status
|
|
|
|
super(TeacherJ, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Журнал преподавания'
|
|
verbose_name_plural = u'Журналы проподавания'
|
|
ordering = ['-id']
|
|
|
|
|
|
class CourseThemeJ(models.Model):
|
|
# Журнал темы
|
|
set_open = models.BooleanField(verbose_name=u'Насильно открыть доступ', default=False)
|
|
success = models.BooleanField(verbose_name=u'Закончено', default=False)
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', null=True)
|
|
parent = models.ForeignKey(TeacherJ, verbose_name=u'Журнал преподавания', blank=True, null=True, editable=False)
|
|
material = models.ForeignKey(CourseTheme, verbose_name=u'Тема')
|
|
date = models.DateTimeField(verbose_name=u'Дата начала', blank=True, null=True)
|
|
f_date = models.DateTimeField(verbose_name=u'Дата завершения', blank=True, null=True)
|
|
actual_lesson = models.ForeignKey(Lesson, verbose_name=u'Актуальны урок для этой темы', blank=True, null=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s: %s %s' % (self.id, self.material, self.student)
|
|
|
|
def __str__(self):
|
|
return '%s: %s %s' % (self.id, self.material, self.student)
|
|
|
|
def reload_progress(self):
|
|
self.parent.reload_progress()
|
|
|
|
def get_teacher(self):
|
|
return self.parent.get_teacher()
|
|
|
|
def saw_this(self):
|
|
do = []
|
|
if not LessonJ.objects.filter(parent=self).exclude(success=True).exists():
|
|
do.append(True)
|
|
if not HomeworkJ.objects.filter(parent=self).exclude(success=True).exists():
|
|
do.append(True)
|
|
if not ExamJ.objects.filter(parent=self).exclude(success=True).exists():
|
|
do.append(True)
|
|
if not self.success:self.success = True
|
|
if not self.f_date: self.f_date = datetime.datetime.now()
|
|
if len(do) == 3: self.save();self.reload_progress()
|
|
|
|
def make_actual_lesson(self):
|
|
# Заполнить актуальный ID журнала урока
|
|
if Lesson.objects.filter(theme=self.material).exists():
|
|
if self.material._type != 'Ex':
|
|
for i in LessonJ.objects.filter(parent=self).order_by('-material__sort'):
|
|
if i.get_status_flag() in ['A', 'F']:
|
|
return i.material.id
|
|
return None
|
|
|
|
def get_status_flag(self):
|
|
# Если success - закончен
|
|
if self.success:
|
|
return 'F'
|
|
|
|
elif self.date and not self.f_date:
|
|
return 'A'
|
|
|
|
elif self.date and self.f_date and not self.success:
|
|
# Поставить success = True если по условиям он должен быть
|
|
self.success = True
|
|
self.save()
|
|
return 'F'
|
|
|
|
elif self.material._type != 'Ex' and LessonJ.objects.filter(parent=self).exists():
|
|
return LessonJ.objects.filter(parent=self).first().get_status_flag()
|
|
|
|
elif self.material._type == 'Ex':
|
|
try:
|
|
return ExamJ.objects.get(parent=self).get_status_flag()
|
|
except ExamJ.DoesNotExist:
|
|
return 'N'
|
|
return 'N'
|
|
|
|
def get_status(self):
|
|
return search_in_collection(STATUS_COLLECTION, 'flag', self.get_status_flag())
|
|
|
|
def get_empty_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'type': self.material.get_type(),
|
|
'title': self.material.get_title(),
|
|
'status': self.get_status(),
|
|
'description': self.material.get_description() if self.material._type != 'Ex' else '',
|
|
'skills': self.material.get_skills(), # skill_template
|
|
'sort': self.material.sort,
|
|
'actual_lesson': self.actual_lesson,
|
|
'button': self.get_button(),
|
|
'lessons_length': self.material.lessons_length(),
|
|
'homeworks_length': self.material.homework_length(),
|
|
'icon': self.material.get_icon()
|
|
}
|
|
|
|
def get_empty_face(self, user):
|
|
return {
|
|
'head': self.get_head_face(),
|
|
'parent': self.parent,
|
|
'lessons': (journal.get_empty_head_face() for journal in LessonJ.objects.filter(parent=self)),
|
|
'homework': list(journal.get_empty_head_face() for journal in HomeworkJ.objects.filter(parent=self)),
|
|
'exam': (journal.get_empty_head_face() for journal in ExamJ.objects.filter(parent=self)), # exam_template
|
|
}
|
|
|
|
def get_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'type': self.material.get_type(),
|
|
'title': self.material.get_title(),
|
|
'status': self.get_status(), # status_template
|
|
'description': self.material.get_description() if self.material._type != 'Ex' else '',
|
|
'skills': self.material.get_skills(), # skill_template
|
|
'sort': self.material.sort,
|
|
'actual_lesson': self.actual_lesson,
|
|
'button': self.get_button(),
|
|
'lessons_length': self.material.lessons_length(),
|
|
'homeworks_length': self.material.homework_length(),
|
|
'icon': self.material.get_icon()
|
|
}
|
|
|
|
def get_face(self, user):
|
|
# Получить лицо темы
|
|
return {
|
|
'head': self.get_head_face(),
|
|
'parent': self.parent,
|
|
'lessons': (journal.get_head_face() for journal in LessonJ.objects.filter(parent=self)),
|
|
'homework': list(journal.get_head_face() for journal in HomeworkJ.objects.filter(parent=self)),
|
|
'exam': (journal.get_head_face() for journal in ExamJ.objects.filter(parent=self)), # exam_template
|
|
}
|
|
|
|
def get_statistic_face(self):
|
|
# Цвета:
|
|
# Серый - не доступен
|
|
# Зеленый - все сдано в течении 2х дней
|
|
# Синий - уроки пройдены/дз открыто
|
|
# Оранжевый - прохождение больше 2х дней и количество попыток внутрь
|
|
# Работа зажержана на неделю
|
|
color = 'default'
|
|
if not self.date or not self.f_date:
|
|
color = 'default'
|
|
elif (self.f_date and self.success) and (self.f_date - self.date).days < 2:
|
|
color = 'success'
|
|
elif (self.f_date - self.date).days < 2 and HomeworkJ.objects.filter(material__theme=self.material,
|
|
f_date=None).exists():
|
|
color = 'primary'
|
|
elif (self.f_date - self.date).days > 2 and HomeworkJ.objects.filter(material__theme=self.material,
|
|
f_date=None).exists():
|
|
color = 'warning'
|
|
elif (self.f_date - self.date).days > 14 and HomeworkJ.objects.filter(material__theme=self.material,
|
|
f_date=None).exists():
|
|
color = 'danger'
|
|
return {
|
|
'color': color,
|
|
'tries': ExamTry.objects.filter(
|
|
material__theme=self.material).count() if self.material._type != 'Ex' else HomeworkTry.objects.filter(
|
|
material__theme=self.material).count()
|
|
}
|
|
|
|
def get_button(self):
|
|
# Выводить только кнопки Экзамена или урока
|
|
try:
|
|
if self.material._type == 'Ex':
|
|
return ExamJ.objects.get(parent=self).get_button()
|
|
else:
|
|
if not self.actual_lesson:
|
|
return LessonJ.objects.get(material=self.make_actual_lesson(), parent=self).get_button()
|
|
return LessonJ.objects.get(material=self.actual_lesson, parent=self).get_button()
|
|
except ExamJ.DoesNotExist:
|
|
check_journal(self.parent)
|
|
except LessonJ.DoesNotExist:
|
|
check_journal(self.parent)
|
|
|
|
def check_pay(self):
|
|
return self.parent.check_pay(__type=self.material.price_type)
|
|
|
|
def get_parent(self):
|
|
# Определение родителя объекта
|
|
p, c = TeacherJ.objects.get_or_create(student=self.student, course=self.material.course)
|
|
if c:
|
|
p.date = datetime.datetime.now()
|
|
p.save()
|
|
return p
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.parent:
|
|
self.parent = self.get_parent()
|
|
actual_lesson = self.make_actual_lesson()
|
|
|
|
if not self.date and self.f_date:
|
|
self.date = self.f_date
|
|
|
|
if actual_lesson:
|
|
if not self.actual_lesson:
|
|
self.actual_lesson = Lesson.objects.get(id=self.make_actual_lesson())
|
|
elif actual_lesson != self.actual_lesson.id:
|
|
self.actual_lesson = Lesson.objects.get(id=self.make_actual_lesson())
|
|
|
|
if LessonJ.objects.filter(parent=self, student=self.student).exists():
|
|
if LessonJ.objects.filter(parent=self, student=self.student, success=False).exists():
|
|
self.success = False
|
|
else:
|
|
self.success = True
|
|
|
|
if self.set_open:
|
|
if Lesson.objects.filter(theme=self.material).order_by('sort').exists():
|
|
lesson = Lesson.objects.filter(theme=self.material).order_by('sort')[0]
|
|
else:
|
|
lesson = CourseMap.objects.filter(course=self.material.course).order_by('-sort')[0]
|
|
|
|
if self.material._type != 'Ex' and not self.parent.opens.filter(token=lesson.token).exists():
|
|
self.parent.opens.add(CourseMap.objects.get(token=lesson.token))
|
|
set_opened(self.parent, lesson.token)
|
|
|
|
elif self.material._type == 'Ex' and not self.parent.opens.filter(id=CourseMap.objects.get(token=Exam.objects.get(theme=self.material).token).id).exists():
|
|
set_opened(self.parent, Exam.objects.get(theme=self.material).token)
|
|
|
|
super(CourseThemeJ, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Журнал темы'
|
|
verbose_name_plural = u'Журнал темы'
|
|
ordering = ['material__sort']
|
|
|
|
|
|
class LessonJ(models.Model):
|
|
# Журнал урока
|
|
set_open = models.BooleanField(verbose_name=u'Насильно открыть доступ', default=False)
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', null=True)
|
|
success = models.BooleanField(verbose_name=u'Пройдено', default=False)
|
|
material = models.ForeignKey(Lesson, verbose_name=u'Урок')
|
|
parent = models.ForeignKey(CourseThemeJ, verbose_name=u'Журнал темы', blank=True, null=True, editable=False)
|
|
date = models.DateTimeField(verbose_name=u'Дата начала', null=True, blank=True)
|
|
f_date = models.DateTimeField(verbose_name=u'Дата завернешия', blank=True, null=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s:%s %s %s' % (self.id, self.student, self.material, self.success)
|
|
|
|
def __str__(self):
|
|
return '%s:%s %s %s' % (self.id, self.student, self.material, self.success)
|
|
|
|
def get_status_flag(self):
|
|
if self.success:
|
|
return 'F'
|
|
elif CourseMap.objects.filter(token=u'{0}#{1}'.format(self.material.course.id, 0),
|
|
lesson=self.material).exists() or self.date:
|
|
return 'A'
|
|
return 'N'
|
|
|
|
def get_teacher(self):
|
|
return self.parent.get_teacher()
|
|
|
|
def get_status(self):
|
|
return search_in_collection(STATUS_COLLECTION, 'flag', self.get_status_flag(), in_type='L')
|
|
|
|
def get_empty_head_face(self):
|
|
if self.material.on_comment == 'T':
|
|
on_comment = self.material.theme.on_comment
|
|
elif self.material.on_comment == 'N':
|
|
on_comment = True
|
|
else:
|
|
on_comment = False
|
|
|
|
return {
|
|
'title': self.material.get_title(),
|
|
'status': self.get_status(),
|
|
'skills': self.material.get_skills(),
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'sort': self.material.sort,
|
|
'button': self.get_button(),
|
|
'on_comment': on_comment
|
|
}
|
|
|
|
def get_empty_face(self, user):
|
|
return {
|
|
'head': self.get_empty_head_face(),
|
|
'description': self.material.get_description(),
|
|
'video': self.material.video,
|
|
'comments': self.material.get_comments(_user=user),
|
|
'next': self.get_next()
|
|
}
|
|
|
|
def get_head_face(self):
|
|
if self.material.on_comment == 'T':
|
|
on_comment = self.material.theme.on_comment
|
|
elif self.material.on_comment == 'N':
|
|
on_comment = True
|
|
else:
|
|
on_comment = False
|
|
|
|
return {
|
|
'title': self.material.get_title(),
|
|
'status': self.get_status(),
|
|
'skills': self.material.get_skills(),
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'sort': self.material.sort,
|
|
'button': self.get_button(),
|
|
'on_comment': on_comment
|
|
}
|
|
|
|
def get_face(self, user):
|
|
if self.student:
|
|
return {
|
|
'head': self.get_head_face(),
|
|
'description': self.material.get_description(),
|
|
'video': self.material.video,
|
|
'comments': self.material.get_comments(_user=user),
|
|
'next': self.get_next(),
|
|
'materials': self.material.get_materials()
|
|
}
|
|
else:
|
|
return self.get_empty_face(user)
|
|
|
|
def get_button(self):
|
|
b = search_in_collection(BUTTON_TYPE, 'flag', 'A', in_type='L')
|
|
b['course'] = self.material.course.id
|
|
b['id'] = self.material.id
|
|
return b
|
|
|
|
def get_next(self):
|
|
try:
|
|
_next = CourseMap.objects.get(token=self.material.token)
|
|
except CourseMap.DoesNotExist:
|
|
_next = CourseMap.objects.get(token=self.material.course.build_map(material=self.material))
|
|
_type, _next = _next.get_next()
|
|
if _type == 'L':
|
|
obj = LessonJ
|
|
elif _type == 'H':
|
|
obj = HomeworkJ
|
|
elif _type == 'E':
|
|
obj = ExamJ
|
|
|
|
j, c = obj.objects.get_or_create(material=_next, student=self.student)
|
|
if self.success:
|
|
j.open_material()
|
|
return {'button': search_in_collection(BUTTON_TYPE,
|
|
'flag',
|
|
'A',
|
|
in_type=_type),
|
|
'obj': _next,
|
|
'journal': j,
|
|
'type': _type}
|
|
|
|
def get_before(self):
|
|
try:
|
|
_before = CourseMap.objects.get(token=self.material.token)
|
|
except CourseMap.DoesNotExist:
|
|
_before = CourseMap.objects.get(token=self.material.course.build_map(material=self.material))
|
|
_type, _before = _before.get_before()
|
|
|
|
if _type == 'L':
|
|
obj = LessonJ
|
|
elif _type == 'H':
|
|
obj = HomeworkJ
|
|
elif _type == 'E':
|
|
obj = ExamJ
|
|
|
|
j = obj.objects.get(material=_before, student=self.student)
|
|
if j.success:
|
|
self.open_material()
|
|
return {'button': search_in_collection(BUTTON_TYPE,
|
|
'flag',
|
|
'A',
|
|
in_type=_type),
|
|
'obj': _before,
|
|
'journal': j,
|
|
'type': _type}
|
|
|
|
def open_material(self):
|
|
try:
|
|
point = AchievementsMap.objects.get(point=CourseMap.objects.get(token=self.material.token), after=False)
|
|
except AchievementsMap.DoesNotExist:
|
|
pass
|
|
else:
|
|
if point.achiv:
|
|
if not AchievementJ.objects.filter(student=self.student, achievement=point.achiv).exists():
|
|
AchievementJ.objects.create(group=self.material.course.get_title(),
|
|
title=self.material.get_title(),
|
|
student=self.student, achievement=point.achiv)
|
|
|
|
do = False
|
|
self_do = False
|
|
if not self.parent: self.parent = self.get_parent();self_do = True
|
|
if not self.date: self.date = datetime.datetime.now();self_do = True
|
|
if not self.parent.date: self.parent.date = datetime.datetime.now();do = True
|
|
|
|
if self.parent.parent.lesson and not CourseMap.objects.get(lesson=self.material).sort <= CourseMap.objects.get(lesson=self.parent.parent.lesson).sort:
|
|
self.parent.parent.lesson = self.material; do = True
|
|
|
|
if self_do: self.save()
|
|
if do: self.parent.save()
|
|
|
|
def saw_this(self):
|
|
try:
|
|
point = AchievementsMap.objects.get(point=CourseMap.objects.get(token=self.material.token), after=True)
|
|
except AchievementsMap.DoesNotExist:
|
|
pass
|
|
else:
|
|
if not AchievementJ.objects.filter(student=self.student, achievement=point.achiv).exists():
|
|
AchievementJ.objects.create(group=self.material.course.get_title(),
|
|
title=self.material.get_title(),
|
|
student=self.student, achievement=point.achiv)
|
|
if self.parent.parent.waiting.filter(token=self.material.token).exists():
|
|
self.parent.parent.waiting.remove(CourseMap.objects.get(token=self.material.token))
|
|
do = False
|
|
if not self.success: self.success = True;do=True
|
|
if not self.f_date: self.f_date = datetime.datetime.now();do=True
|
|
if do: self.save()
|
|
self.parent.reload_progress()
|
|
_next = self.get_next()
|
|
_next['journal'].open_material()
|
|
|
|
def check_parent_success(self):
|
|
# Проверить - нужно ли прочитать родителя
|
|
pass
|
|
|
|
def get_parent(self):
|
|
# Определение родителя объекта
|
|
p, c = CourseThemeJ.objects.get_or_create(student=self.student, material=self.material.theme)
|
|
if c:
|
|
p.date = datetime.datetime.now()
|
|
p.save()
|
|
return p
|
|
|
|
def check_pay(self):
|
|
return self.parent.check_pay()
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.parent:
|
|
self.parent = self.get_parent()
|
|
|
|
if self.set_open and not self.parent.parent.opens.filter(
|
|
id=CourseMap.objects.get(token=self.material.token).id).exists():
|
|
set_opened(self.parent.parent, self.material.token)
|
|
|
|
if self.f_date and self.date and not self.success:
|
|
self.success = True
|
|
|
|
if self.get_status_flag() == 'F':
|
|
if not HomeworkJ.objects.filter(parent=self.parent).exists() and \
|
|
not LessonJ.objects.filter(parent=self.parent, success=False).exclude(id=self.id).exists():
|
|
self.parent.saw_this()
|
|
else:
|
|
self.get_next()['journal'].open_material()
|
|
super(LessonJ, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Журанл урока'
|
|
verbose_name_plural = u'Журналы уроков'
|
|
ordering = ['material__sort']
|
|
|
|
|
|
class HomeworkJ(models.Model):
|
|
# Журнал сдачи работы
|
|
set_open = models.BooleanField(verbose_name=u'Насильно открыть доступ', default=False)
|
|
success = models.BooleanField(verbose_name=u'Закончено', default=False)
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', related_name='h_student', null=True)
|
|
teacher = models.ForeignKey(User, verbose_name=u'Экзаменатор', related_name='h_teacher', blank=True, null=True)
|
|
material = models.ForeignKey(Homework, verbose_name=u'Домашнее задание')
|
|
parent = models.ForeignKey(CourseThemeJ, verbose_name=u'Журнал темы', blank=True, null=True, editable=False)
|
|
date = models.DateTimeField(verbose_name=u'Дата предоставления доступа', null=True, blank=True)
|
|
f_date = models.DateTimeField(verbose_name=u'Дата звершения', null=True, blank=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s' % (self.student, self.success)
|
|
|
|
def __str__(self):
|
|
return '%s %s' % (self.student, self.success)
|
|
|
|
def get_status_flag(self):
|
|
if self.success:
|
|
return 'F'
|
|
else:
|
|
if HomeworkTry.objects.filter(parent=self).exists():
|
|
return HomeworkTry.objects.filter(parent=self).last().get_status_flag()
|
|
elif self.date:
|
|
return 'A'
|
|
return 'N'
|
|
|
|
def get_teacher(self):
|
|
#if self.get_trues_length() != 0:
|
|
# ex = HomeworkTry.objects.filter(parent=self).exclude(teacher=None).last()
|
|
# if ex:
|
|
# return ex.teacher
|
|
return self.parent.get_teacher()
|
|
|
|
def get_status(self):
|
|
return search_in_collection(STATUS_COLLECTION, 'flag', self.get_status_flag(), in_type='H')
|
|
|
|
def get_empty_face(self, user):
|
|
return {
|
|
'head': self.get_empty_head_face(),
|
|
'materials': [],
|
|
'tries': []
|
|
}
|
|
|
|
def get_empty_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': search_in_collection(STATUS_COLLECTION, 'flag', 'N', in_type='H'),
|
|
'description': '',
|
|
'button': self.get_button(),
|
|
'delay': {'status': False,
|
|
'description': ''}
|
|
}
|
|
|
|
def get_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': self.get_status(),
|
|
'button': self.get_button(),
|
|
'title': self.material.get_title(),
|
|
'description': self.material.get_description(),
|
|
'delay': {'status': True if (self.teacher and self.teacher.delay) else False,
|
|
'description': self.teacher.delay_description if self.teacher and self.teacher.delay else ''}
|
|
}
|
|
|
|
def get_face(self, user):
|
|
if self.student:
|
|
return {
|
|
'head': self.get_head_face(),
|
|
'materials': self.material.get_materials(),
|
|
'tries': [_try.get_face(user) for _try in HomeworkTry.objects.filter(parent=self)],
|
|
'next': self.get_next(),
|
|
'teacher': self.teacher
|
|
}
|
|
else:
|
|
return self.get_empty_face(user)
|
|
|
|
def get_trues_length(self):
|
|
return HomeworkTry.objects.filter(parent=self).count()
|
|
|
|
def get_button(self):
|
|
b = search_in_collection(BUTTON_TYPE, 'flag', 'A', in_type='H')
|
|
b['course'] = self.material.course.id
|
|
b['id'] = self.material.id
|
|
return b
|
|
|
|
def get_next(self):
|
|
try:
|
|
_next = CourseMap.objects.get(token=self.material.token)
|
|
except CourseMap.DoesNotExist:
|
|
_next = CourseMap.objects.get(token=self.material.course.build_map(material=self.material))
|
|
_type, _next = _next.get_next()
|
|
if _type == 'L':
|
|
obj = LessonJ
|
|
elif _type == 'H':
|
|
obj = HomeworkJ
|
|
elif _type == 'E':
|
|
obj = ExamJ
|
|
|
|
j = obj.objects.get(material=_next, student=self.student)
|
|
if self.success:
|
|
j.open_material()
|
|
return {'button': search_in_collection(BUTTON_TYPE,
|
|
'flag',
|
|
'A',
|
|
in_type=_type),
|
|
'obj': _next,
|
|
'journal': j,
|
|
'type': _type}
|
|
|
|
def get_before(self):
|
|
try:
|
|
_before = CourseMap.objects.get(token=self.material.token)
|
|
except CourseMap.DoesNotExist:
|
|
_before = CourseMap.objects.get(token=self.material.course.build_map(material=self.material))
|
|
_type, _before = _before.get_before()
|
|
if _type == 'L':
|
|
obj = LessonJ
|
|
elif _type == 'H':
|
|
obj = HomeworkJ
|
|
elif _type == 'E':
|
|
obj = ExamJ
|
|
|
|
j = obj.objects.get(material=_before, student=self.student)
|
|
if self.success:
|
|
j.open_material()
|
|
return {'button': search_in_collection(BUTTON_TYPE,
|
|
'flag',
|
|
'A',
|
|
in_type=_type),
|
|
'obj': _before,
|
|
'journal': j,
|
|
'type': _type}
|
|
|
|
def open_next(self):
|
|
material = self.get_next()
|
|
if material['type'] == 'L' and material['journal'].get_status_flag() == 'N':
|
|
material['journal'].open_material()
|
|
|
|
def saw_this(self):
|
|
try:
|
|
point = AchievementsMap.objects.get(point=CourseMap.objects.get(token=self.material.token), after=True)
|
|
except AchievementsMap.DoesNotExist:
|
|
pass
|
|
else:
|
|
if not AchievementJ.objects.filter(student=self.student, achievement=point.achiv).exists():
|
|
AchievementJ.objects.create(group=self.material.course.get_title(),
|
|
title=self.material.get_title(),
|
|
student=self.student, achievement=point.achiv)
|
|
if self.parent.parent.waiting.filter(token=self.material.token).exists():
|
|
self.parent.parent.waiting.remove(CourseMap.objects.get(token=self.material.token))
|
|
do = True
|
|
if not self.success:self.success = True;do=True
|
|
if not self.f_date: self.f_date = datetime.datetime.now();do=True
|
|
if do: self.save()
|
|
if self.parent.parent.homework and not CourseMap.objects.get(homework=self.material).sort <= CourseMap.objects.get(
|
|
homework=self.parent.parent.homework).sort:
|
|
self.parent.parent.homework = self.material
|
|
self.parent.parent.save()
|
|
self.parent.saw_this()
|
|
self.parent.reload_progress()
|
|
_next = self.get_next()
|
|
if LessonJ.objects.filter(parent=_next['journal'].parent).exclude(success=True).exists():
|
|
_next['journal'].open_material()
|
|
elif HomeworkJ.objects.filter(parent=_next['journal'].parent).exclude(success=True).exists():
|
|
HomeworkJ.objects.filter(parent=_next['journal'].parent).exclude(success=True).first().open_material()
|
|
|
|
|
|
def check_pay(self):
|
|
return self.parent.check_pay()
|
|
|
|
def open_material(self):
|
|
if not HomeworkJ.objects.filter(parent__parent=self.parent.parent).exclude(Q(date=None)|Q(success=True)).exists():
|
|
try:
|
|
point = AchievementsMap.objects.get(point=CourseMap.objects.get(token=self.material.token), after=False)
|
|
except AchievementsMap.DoesNotExist:
|
|
pass
|
|
else:
|
|
if not AchievementJ.objects.filter(student=self.student, achievement=point.achiv).exists():
|
|
AchievementJ.objects.create(group=self.material.course.get_title(),
|
|
title=self.material.get_title(),
|
|
student=self.student, achievement=point.achiv)
|
|
do = False
|
|
self_do = False
|
|
if not self.parent: self.parent = self.get_parent();self_do = True
|
|
if not self.date: self.date = datetime.datetime.now();self_do = True
|
|
if not self.parent.date: self.parent.date = datetime.datetime.now();do = True
|
|
if do: self.parent.save()
|
|
if self_do: self.save()
|
|
|
|
def get_parent(self):
|
|
# Определение родителя объекта
|
|
p, c = CourseThemeJ.objects.get_or_create(student=self.student, material=self.material.theme)
|
|
if c:
|
|
p.date = datetime.datetime.now()
|
|
p.save()
|
|
return p
|
|
|
|
def get_tries(self, user=None):
|
|
return [i.get_face(user) for i in HomeworkTry.objects.filter(parent=self)]
|
|
|
|
def check_expired(self):
|
|
return HomeworkTry.objects.filter(parent=self, expired=True).exists()
|
|
|
|
def expired_time(self):
|
|
# Общее время просрочки по домашнему заданию в часах
|
|
result = 0
|
|
for t in HomeworkTry.objects.filter(parent=self, expired=True):
|
|
result += t.get_expired_time()
|
|
return result
|
|
|
|
def get_url(self):
|
|
return u'{0}/teacher/workshop/homework/{1}'.format(DOMAIN, self.id)
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.parent:
|
|
self.parent = self.get_parent()
|
|
|
|
if self.set_open and not self.parent.parent.opens.filter(
|
|
id=CourseMap.objects.get(token=self.material.token).id).exists():
|
|
set_opened(self.parent.parent, self.material.token)
|
|
|
|
# Выставить статус теме
|
|
if self.f_date and self.date and not self.success:
|
|
self.success = True
|
|
|
|
if not self.teacher and self.get_status_flag() != 'N':
|
|
self.teacher = self.get_teacher()
|
|
|
|
if self.get_status_flag() == 'F':
|
|
if not HomeworkJ.objects.filter(parent=self.parent, success=False).exclude(id=self.id).exists():
|
|
self.parent.saw_this()
|
|
else:
|
|
self.get_next()['journal'].open_material()
|
|
super(HomeworkJ, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Журнал домашней работы'
|
|
verbose_name_plural = u'Журналы домашних работ'
|
|
ordering = ['material__sort']
|
|
|
|
|
|
class HomeworkTry(models.Model):
|
|
# Попытка сдачи экзамена
|
|
parent = models.ForeignKey(HomeworkJ, verbose_name=u'Журнал', blank=True, null=True, editable=False)
|
|
material = models.ForeignKey(Homework, verbose_name=u'Домашнее задание')
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', related_name='h_t_student')
|
|
teacher = models.ForeignKey(User, verbose_name=u'Преподаватель', related_name='h_t_teacher', blank=True, null=True)
|
|
new_teach = models.ForeignKey(User, verbose_name=u'Новый преподаватель', related_name='h_t_new_teacher', blank=True, null=True)
|
|
date = models.DateTimeField(verbose_name=u'Начало', default=datetime.datetime.now)
|
|
f_date = models.DateTimeField(verbose_name=u'Завершение', blank=True, null=True)
|
|
success = models.BooleanField(verbose_name=u'Одобрено', default=False)
|
|
expired = models.BooleanField(verbose_name=u'Просрочено', default=False)
|
|
comments = models.ManyToManyField(Comment, verbose_name=u'Общение', blank=True, editable=False)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s %s' % (self.material, self.student, self.f_date)
|
|
|
|
def __str__(self):
|
|
return '%s %s %s' % (self.material, self.student, self.f_date)
|
|
|
|
def get_teacher(self):
|
|
#if not self.teacher:
|
|
return self.parent.get_teacher()
|
|
|
|
def saw_this(self):
|
|
do = False
|
|
if not self.success: self.success=True;do=True
|
|
if not self.f_date: self.f_date=datetime.datetime.now();do=True
|
|
if do: self.save()
|
|
self.parent.saw_this()
|
|
|
|
def get_status_flag(self):
|
|
# Получить флаг статуса
|
|
if not self.success and self.f_date:
|
|
return u'E'
|
|
elif self.success and self.f_date:
|
|
return u'F'
|
|
elif self.date and not self.f_date:
|
|
try:
|
|
self.comments.exists()
|
|
except:
|
|
return 'A'
|
|
else:
|
|
return 'T'
|
|
else:
|
|
return 'N'
|
|
|
|
def expired_for(self):
|
|
return '<span class="label label-danger">Просрочено</span>' if self.expired else '<span class="label label-info">' + str(
|
|
datetime.datetime.now() - (self.date + datetime.timedelta(hours=1)))[:8] + '</span>'
|
|
|
|
def get_expired_time(self):
|
|
# На сколько часов просрочена проверка
|
|
d = self.f_date if self.f_date else datetime.datetime.now()
|
|
return (d - self.date).seconds/60/60
|
|
|
|
def get_status(self):
|
|
# Результат возвращается по шаблону
|
|
return search_in_collection(STATUS_COLLECTION, 'flag', self.get_status_flag(), in_type='HT')
|
|
|
|
def get_comments(self, user):
|
|
# Получить все комментарии урока
|
|
return [comment_fabric(comment, __type='HT', __user=user) for comment in self.comments.all()]
|
|
|
|
def get_empty_face(self, user):
|
|
return {}
|
|
|
|
def get_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': self.get_status(),
|
|
'teacher': {
|
|
'short': self.teacher.get_short_name(),
|
|
'full': self.teacher.get_full_name(),
|
|
'ava': self.teacher.get_image_url()
|
|
},
|
|
'delay': {'status': True if (self.teacher and self.teacher.delay) else False,
|
|
'description': self.teacher.delay_description if self.teacher and self.teacher.delay else ''}
|
|
}
|
|
|
|
def get_face(self, user):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': self.get_status(),
|
|
'comments': self.get_comments(user),
|
|
'date_start': out_date_format(self.date),
|
|
'date_finish': out_date_format(self.f_date),
|
|
'teacher': self.teacher
|
|
}
|
|
|
|
def check_pay(self):
|
|
return self.parent.check_pay()
|
|
|
|
def get_parent(self):
|
|
# Определение родителя объекта
|
|
p, c = HomeworkJ.objects.get_or_create(student=self.student, material=self.material)
|
|
if c:
|
|
p.date = datetime.datetime.now()
|
|
p.save()
|
|
return p
|
|
|
|
def get_url(self):
|
|
self.parent.get_url()
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.parent:
|
|
self.parent = self.get_parent()
|
|
|
|
#if (self.teacher and self.new_teach) and (self.teacher != self.new_teach):
|
|
# self.teacher = self.new_teach
|
|
#else:
|
|
if not self.teacher:
|
|
if not self.get_teacher():
|
|
teacher = self.parent.parent.parent.teacher_to_set()
|
|
self.teacher = teacher
|
|
self.parent.teacher = teacher
|
|
self.parent.save()
|
|
self.parent.parent.parent.teacher = teacher
|
|
self.parent.parent.parent.save()
|
|
else:
|
|
self.teacher = self.get_teacher()
|
|
|
|
if self.get_status_flag() not in ['N', 'F']:
|
|
self.parent.open_next()
|
|
|
|
if self.get_status_flag() == 'F' and self.parent.get_status_flag() != 'F':
|
|
self.parent.saw_this()
|
|
|
|
super(HomeworkTry, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Попытка сдачи ДЗ'
|
|
verbose_name_plural = u'Попытки сдачи ДЗ'
|
|
ordering = ['date']
|
|
|
|
|
|
class ExamJ(models.Model):
|
|
# Журнал экзамена
|
|
set_open = models.BooleanField(verbose_name=u'Насильно открыть доступ', default=False)
|
|
success = models.BooleanField(verbose_name=u'Пройдено', default=False)
|
|
material = models.ForeignKey(Exam, verbose_name=u'Экзамен', null=True)
|
|
parent = models.ForeignKey(CourseThemeJ, verbose_name=u'Журнал', blank=True, null=True, editable=False)
|
|
student = models.ForeignKey(User, verbose_name=u'Экзаменуемый', related_name='e_student', null=True)
|
|
teacher = models.ForeignKey(User, verbose_name=u'Экзаменатор', related_name='e_teacher', blank=True, null=True)
|
|
date = models.DateTimeField(verbose_name=u'Дата', null=True, blank=True)
|
|
f_date = models.DateTimeField(verbose_name=u'Дата завершения', blank=True, null=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s' % (self.student, self.success)
|
|
|
|
def __str__(self):
|
|
return '%s %s' % (self.student, self.success)
|
|
|
|
def get_teacher(self):
|
|
return self.parent.get_teacher()
|
|
|
|
def get_url(self):
|
|
return u'{0}/teacher/workshop/exam/{1}'.format(DOMAIN, self.id)
|
|
|
|
def get_status_flag(self):
|
|
if self.success:
|
|
return 'F'
|
|
else:
|
|
if ExamTry.objects.filter(parent=self).exists():
|
|
return ExamTry.objects.filter(parent=self).last().get_status_flag()
|
|
else:
|
|
if self.date:
|
|
return 'A'
|
|
return 'N'
|
|
|
|
def get_status(self):
|
|
return search_in_collection(STATUS_COLLECTION, 'flag', self.get_status_flag(), in_type='E')
|
|
|
|
def get_empty_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': search_in_collection(STATUS_COLLECTION, 'flag', 'N', in_type='E'),
|
|
'description': '',
|
|
'title': u'Экзаменационная работа',
|
|
'button': self.get_button(),
|
|
'teacher': self.teacher
|
|
}
|
|
|
|
def get_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': self.get_status(),
|
|
'description': self.material.get_description() if self.get_status_flag() != 'N' else '',
|
|
'title': u'Экзаменационная работа',
|
|
'button': self.get_button()
|
|
}
|
|
|
|
def get_empty_face(self, user):
|
|
return {
|
|
'head': self.get_empty_head_face(),
|
|
'materials': [],
|
|
'tries': []
|
|
}
|
|
|
|
def get_face(self, user):
|
|
if self.student:
|
|
return {
|
|
'head': self.get_head_face(),
|
|
'materials': self.material.get_materials(),
|
|
'tries': [_try.get_face(user) for _try in ExamTry.objects.filter(parent=self)],
|
|
'next': self.get_next(),
|
|
'teacher': self.teacher
|
|
}
|
|
else:
|
|
return self.get_empty_face(user)
|
|
|
|
def get_button(self):
|
|
b = search_in_collection(BUTTON_TYPE, 'flag', 'A', in_type='E')
|
|
b['course'] = self.material.course.id
|
|
b['id'] = self.material.id
|
|
return b
|
|
|
|
def open_material(self):
|
|
try:
|
|
point = AchievementsMap.objects.get(point=CourseMap.objects.get(token=self.material.token), after=False)
|
|
except AchievementsMap.DoesNotExist:
|
|
pass
|
|
else:
|
|
if not AchievementJ.objects.filter(student=self.student, achievement=point.achiv).exists():
|
|
AchievementJ.objects.create(group=self.material.course.get_title(),
|
|
title=self.material.get_title(),
|
|
student=self.student, achievement=point.achiv)
|
|
do = False
|
|
self_do = False
|
|
if not self.parent: self.parent = self.get_parent();self_do = True
|
|
if not self.date: self.date = datetime.datetime.now();self_do = True
|
|
if not self.parent.date: self.parent.date = datetime.datetime.now();do = True
|
|
if do: self.parent.save()
|
|
if self_do: self.save()
|
|
|
|
def saw_this(self):
|
|
try:
|
|
point = AchievementsMap.objects.get(point=CourseMap.objects.get(token=self.material.token), after=True)
|
|
except AchievementsMap.DoesNotExist:
|
|
pass
|
|
else:
|
|
if not AchievementJ.objects.filter(student=self.student, achievement=point.achiv).exists():
|
|
AchievementJ.objects.create(group=self.material.course.get_title(),
|
|
title=self.material.get_title(),
|
|
student=self.student, achievement=point.achiv)
|
|
if self.parent.parent.waiting.filter(token=self.material.token).exists():
|
|
self.parent.parent.waiting.remove(CourseMap.objects.get(token=self.material.token))
|
|
do = False
|
|
if not self.success: self.success = True;do=True
|
|
if not self.f_date: self.f_date = datetime.datetime.now();do=True
|
|
if do:
|
|
self.save()
|
|
self.parent.reload_progress()
|
|
self.parent.saw_this()
|
|
d, c = DiplomaJ.objects.get_or_create(material=Diploma.objects.get(course=self.material.course), student=self.student)
|
|
if c:
|
|
d.parent = self
|
|
d.save()
|
|
self.get_next()['journal'].open_material()
|
|
|
|
def get_next(self):
|
|
try:
|
|
_next = CourseMap.objects.get(token=self.material.token)
|
|
except CourseMap.DoesNotExist:
|
|
_next = CourseMap.objects.get(token=self.material.course.build_map(material=self.material))
|
|
_type, _next = _next.get_next()
|
|
if _type == 'L':
|
|
obj = LessonJ
|
|
elif _type == 'H':
|
|
obj = HomeworkJ
|
|
elif _type == 'E':
|
|
obj = ExamJ
|
|
|
|
j = obj.objects.get(material=_next, student=self.student)
|
|
if self.success:
|
|
j.open_material()
|
|
return {'button': search_in_collection(BUTTON_TYPE,
|
|
'flag',
|
|
'A',
|
|
in_type=_type),
|
|
'obj': _next,
|
|
'journal': j,
|
|
'type': _type}
|
|
|
|
def get_before(self):
|
|
try:
|
|
_before = CourseMap.objects.get(token=self.material.token)
|
|
except CourseMap.DoesNotExist:
|
|
_before = CourseMap.objects.get(token=self.material.course.build_map(material=self.material))
|
|
_type, _before = _before.get_before()
|
|
if _type == 'L':
|
|
obj = LessonJ
|
|
elif _type == 'H':
|
|
obj = HomeworkJ
|
|
elif _type == 'E':
|
|
obj = ExamJ
|
|
|
|
j = obj.objects.get(material=_before, student=self.student)
|
|
if self.success:
|
|
j.open_material()
|
|
return {'button': search_in_collection(BUTTON_TYPE,
|
|
'flag',
|
|
'A',
|
|
in_type=_type),
|
|
'obj': _before,
|
|
'journal': j,
|
|
'type': _type}
|
|
|
|
def check_pay(self):
|
|
return self.parent.check_pay()
|
|
|
|
def get_parent(self):
|
|
# Определение родителя объекта
|
|
p, c = CourseThemeJ.objects.get_or_create(student=self.student, material=self.material.theme)
|
|
if c:
|
|
p.date = datetime.datetime.now()
|
|
p.save()
|
|
return p
|
|
|
|
def save(self, *args, **kwargs):
|
|
if self.set_open and not self.parent.parent.opens.filter(
|
|
id=CourseMap.objects.get(token=self.material.token).id).exists():
|
|
set_opened(self.parent.parent, self.material.token)
|
|
|
|
if not self.parent:
|
|
self.parent = self.get_parent()
|
|
|
|
if not self.teacher and self.get_status_flag() not in ['F', 'N']:
|
|
self.teacher = self.get_teacher()
|
|
|
|
if self.f_date and self.date and not self.success:
|
|
self.success = True
|
|
|
|
if self.get_status_flag() == 'F':
|
|
if not ExamJ.objects.filter(parent=self.parent, success=False).exclude(id=self.id).exists():
|
|
self.parent.saw_this()
|
|
|
|
else:
|
|
self.get_next()['journal'].open_material()
|
|
|
|
super(ExamJ, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Журнал экзамена'
|
|
verbose_name_plural = u'Журналы экзаменов'
|
|
|
|
|
|
class ExamTry(models.Model):
|
|
# Попытка сдачи экзамена
|
|
parent = models.ForeignKey(ExamJ, verbose_name=u'Журнал', blank=True, null=True, editable=False)
|
|
material = models.ForeignKey(Exam, verbose_name=u'Экзамен')
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', related_name='e_t_student')
|
|
teacher = models.ForeignKey(User, verbose_name=u'Преподаватель', related_name='e_t_teacher', blank=True, null=True)
|
|
date = models.DateTimeField(verbose_name=u'Начало', default=datetime.datetime.now)
|
|
f_date = models.DateTimeField(verbose_name=u'Завершение', blank=True, null=True)
|
|
success = models.BooleanField(verbose_name=u'Успешно', default=False)
|
|
expired = models.BooleanField(verbose_name=u'Просрочено', default=False)
|
|
comments = models.ManyToManyField(Comment, verbose_name=u'Общение', blank=True, editable=False)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s %s' % (self.material, self.student, self.f_date)
|
|
|
|
def __str__(self):
|
|
return '%s %s %s' % (self.material, self.student, self.f_date)
|
|
|
|
def get_status_flag(self):
|
|
# Получить флаг статуса
|
|
if not self.success and self.f_date:
|
|
return u'E'
|
|
elif self.success and self.f_date:
|
|
return u'F'
|
|
elif self.date and not self.f_date:
|
|
try:
|
|
self.comments.exists()
|
|
except:
|
|
return 'A'
|
|
else:
|
|
return 'T'
|
|
else:
|
|
return 'N'
|
|
|
|
def get_teacher(self):
|
|
return self.parent.get_teacher()
|
|
|
|
def get_status(self):
|
|
# Результат возвращается по шаблону
|
|
return search_in_collection(STATUS_COLLECTION, 'flag', self.get_status_flag(), in_type='E')
|
|
|
|
def get_empty_face(self, user):
|
|
return {}
|
|
|
|
def get_comments(self, user):
|
|
# Получить все комментарии урока
|
|
return [comment_fabric(comment, __type='ET', __user=user) for comment in self.comments.all()]
|
|
|
|
def expired_for(self):
|
|
return '<span class="label label-danger">Просрочено</span>' if self.expired else '<span class="label label-info">' + str(
|
|
datetime.datetime.now() - (self.date + datetime.timedelta(hours=1)))[:8] + '</span>'
|
|
|
|
def get_head_face(self):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': self.get_status(),
|
|
'teacher': {
|
|
'short': self.teacher.get_short_name(),
|
|
'full': self.teacher.get_full_name(),
|
|
'ava': self.teacher.get_image_url()
|
|
}
|
|
}
|
|
|
|
def get_face(self, user):
|
|
return {
|
|
'mid': self.material.id,
|
|
'id': self.id,
|
|
'status': self.get_status(),
|
|
'comments': self.get_comments(user),
|
|
'date': out_date_format(self.date),
|
|
'f_date': out_date_format(self.f_date),
|
|
'teacher': self.teacher
|
|
}
|
|
|
|
def check_pay(self):
|
|
return self.parent.check_pay()
|
|
|
|
def get_parent(self):
|
|
# Определение родителя объекта
|
|
p, c = ExamJ.objects.get_or_create(material=self.material, student=self.student)
|
|
if c:
|
|
p.date = datetime.datetime.now()
|
|
p.save()
|
|
return p
|
|
|
|
def saw_this(self):
|
|
do = False
|
|
if not self.success: self.success=True;do=True
|
|
if not self.f_date: self.f_date=datetime.datetime.now();do=True
|
|
if do: self.save()
|
|
self.parent.saw_this()
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.parent:
|
|
self.parent = self.get_parent()
|
|
|
|
if not self.get_teacher():
|
|
teacher = self.parent.parent.parent.teacher_to_set()
|
|
self.teacher = teacher
|
|
self.parent.parent.parent.teacher = teacher
|
|
self.parent.parent.parent.save()
|
|
else:
|
|
self.teacher = self.get_teacher()
|
|
|
|
if self.get_status_flag() == 'F':
|
|
self.saw_this()
|
|
super(ExamTry, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Попытка сдачи Экзамена'
|
|
verbose_name_plural = u'Попытки сдачи Экзаменов'
|
|
ordering = ['date']
|
|
|
|
|
|
class DiplomaJ(models.Model):
|
|
gen = models.BooleanField(verbose_name=u'Сгенерирован', default=False)
|
|
parent = models.ForeignKey(ExamJ, verbose_name=u'Журнал сдачи', blank=True, null=True)
|
|
material = models.ForeignKey(Diploma, verbose_name=u'Шаблон диплома')
|
|
date = models.DateField(verbose_name=u'Дата выдачи', default=datetime.date.today)
|
|
key = models.IntegerField(verbose_name=u'Ключ', blank=True, null=True)
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', null=True)
|
|
out_image = models.ImageField(verbose_name=u'Картинка без печати', upload_to='diploms', blank=True)
|
|
in_image = models.ImageField(verbose_name=u'Картинка c печатью', upload_to='diploms', blank=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s' % (self.material, self.key)
|
|
|
|
def __str__(self):
|
|
return '%s %s' % (self.material, self.key)
|
|
|
|
def get_key(self):
|
|
return '#{0} {1} {2}'.format(str(self.key)[0:3], str(self.key)[3:6], str(self.key)[6:9])
|
|
|
|
def get_name(self):
|
|
return '{0}\n{1}'.format(self.student.name, self.student.fname)
|
|
|
|
def get_date(self):
|
|
return u'{0:%B}_{1}_{2}'.format(self.date, self.date.day, self.date.year)
|
|
|
|
def draw_date(self, _in=None, _out=None):
|
|
if not self.in_image:
|
|
place = self.material.get_place('date')
|
|
_in = gen_write(_in if _in else self.material.in_image.path, self.material.date_font.path,
|
|
self.material.date_size,
|
|
self.get_date(), place[0], place[1], self.material.get_color('date'))
|
|
if not self.out_image:
|
|
place = self.material.get_place('date')
|
|
_out = gen_write(_out if _out else self.material.out_image.path,
|
|
self.material.date_font.path, self.material.date_size,
|
|
self.get_date(), place[0], place[1], self.material.get_color('date'))
|
|
|
|
return _in, _out
|
|
|
|
def draw_name(self, _in=None, _out=None):
|
|
if not self.in_image:
|
|
place = self.material.get_place('name')
|
|
_in = gen_write(_in if _in else self.material.in_image.path, self.material.name_font.path,
|
|
self.material.name_size,
|
|
self.get_name(), place[0], place[1], self.material.get_color('name'))
|
|
if not self.out_image:
|
|
place = self.material.get_place('name')
|
|
_out = gen_write(_out if _out else self.material.out_image.path,
|
|
self.material.name_font.path, self.material.name_size,
|
|
self.get_name(), place[0], place[1], self.material.get_color('name'))
|
|
|
|
return _in, _out
|
|
|
|
def draw_key(self, _in=None, _out=None):
|
|
if not self.key:
|
|
self.key = self.material.get_key()
|
|
if not self.in_image:
|
|
place = self.material.get_place('key')
|
|
_in = gen_write(_in if _in else self.material.in_image.path, self.material.key_font.path,
|
|
self.material.key_size,
|
|
self.get_key(), place[0], place[1], self.material.get_color('key'))
|
|
if not self.out_image:
|
|
place = self.material.get_place('key')
|
|
_out = gen_write(_out if _out else self.material.out_image.path,
|
|
self.material.key_font.path, self.material.key_size,
|
|
self.get_key(), place[0], place[1], self.material.get_color('key'))
|
|
|
|
return _in, _out
|
|
|
|
class Meta:
|
|
verbose_name = u'Журнал дипломов'
|
|
verbose_name_plural = u'Журналы дипломов'
|
|
|
|
|
|
class AchievementJ(models.Model):
|
|
# Журнал достижений
|
|
group = models.CharField(verbose_name=u'Раздел', max_length=100, default='')
|
|
title = models.CharField(verbose_name=u'Заголовок', max_length=255)
|
|
text = models.TextField(verbose_name=u'Текст достижения', blank=True)
|
|
student = models.ForeignKey(User, verbose_name=u'Студент')
|
|
achievement = models.ForeignKey(Achievements, verbose_name=u'Шаблон достижения')
|
|
got = models.BooleanField(verbose_name=u'Получено', default=False)
|
|
date = models.DateField(verbose_name=u'Дата получения', default=datetime.date.today)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s %s %s' % (self.title, self.student, self.date, self.got)
|
|
|
|
def __str__(self):
|
|
return '%s %s %s %s' % (self.title, self.student, self.date, self.got)
|
|
|
|
class Meta:
|
|
verbose_name = u'Журнал достижений'
|
|
verbose_name_plural = u'Журналы достижений'
|
|
|
|
|
|
class ReportDepth(models.Model):
|
|
REPORT_FLAG = (
|
|
('G', '#99CC99'),
|
|
('Y', '#FFFF99'),
|
|
('R', '#FF3300')
|
|
)
|
|
token = models.ForeignKey(CourseMap, verbose_name=u'Точка курса')
|
|
student = models.ForeignKey(User, verbose_name=u'Студент', related_name='depth_report_student')
|
|
teacher = models.ForeignKey(User, verbose_name=u'Преподаватель', related_name='depth_report_teacher', blank=True, null=True)
|
|
course = models.ForeignKey(Course, verbose_name=u'Курс')
|
|
s_date = models.DateTimeField(verbose_name=u'Дата старта', default=datetime.datetime.now)
|
|
f_date = models.DateTimeField(verbose_name=u'Дата завершения', blank=True, null=True)
|
|
flag = models.CharField(verbose_name=u'Флаг выполнения', choices=REPORT_FLAG, max_length=1, blank=True, null=True)
|
|
|
|
def __unicode__(self):
|
|
return u'%s %s' % (self.id, self.token)
|
|
|
|
def __str__(self):
|
|
return '%s %s' % (self.id, self.token)
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.flag and self.f_date:
|
|
d = (self.s_date - self.f_date).days
|
|
if d <= 1:
|
|
self.flag = 'G'
|
|
elif 1 < d < 3:
|
|
self.flag = 'Y'
|
|
elif d > 3:
|
|
self.flag = 'R'
|
|
super(ReportDepth, self).save(*args, **kwargs)
|
|
|
|
class Meta:
|
|
verbose_name = u'Глубокий отчет'
|
|
verbose_name_plural = u'Глубокий отчет'
|
|
ordering = ['s_date']
|
|
|
|
|
|
def multiple_exclude(student, material, _type=None):
|
|
__tmp = None
|
|
good = None
|
|
if _type == 'L':
|
|
__tmp = LessonJ.objects.filter(student=student, material=material).order_by('date')
|
|
|
|
elif _type == 'H':
|
|
__tmp = HomeworkJ.objects.filter(student=student, material=material).order_by('date')
|
|
|
|
elif _type == 'E':
|
|
__tmp = ExamJ.objects.filter(student=student, material=material).order_by('date')
|
|
|
|
if __tmp:
|
|
for tmp in __tmp:
|
|
if not good:
|
|
good = tmp
|
|
else:
|
|
tmp.delete()
|
|
|
|
return good
|
|
|
|
|
|
def check_journal(journal, from_console=False):
|
|
# Получить все курсы в теме
|
|
materials = {
|
|
'themes': [],
|
|
'lessons': {},
|
|
'homework': {},
|
|
'exam': {}
|
|
}
|
|
|
|
if not from_console:
|
|
f = open(os.path.join(BASE_DIR, 'journals/check_switch'), 'r')
|
|
if f.read().strip() == '1':
|
|
return None
|
|
|
|
#print '=============='
|
|
#print 'CourseThemeMap'
|
|
for CT in CourseTheme.objects.filter(course=journal.course):
|
|
try:
|
|
t = CourseThemeJ.objects.get_or_create(material=CT, student=journal.student, parent=journal)[0]
|
|
except CourseThemeJ.MultipleObjectsReturned:
|
|
t = None
|
|
for i in CourseThemeJ.objects.filter(material=CT, student=journal.student, parent=journal).order_by('date'):
|
|
if not t:
|
|
t = i
|
|
else:
|
|
i.delete()
|
|
materials['themes'].append(t)
|
|
|
|
# Проверить журналы пользователя по материалу, если нет, создать
|
|
|
|
for theme in materials['themes']:
|
|
# print 'CourseTheme'
|
|
# print '============ Начинаю новую тему'
|
|
# print theme
|
|
# print 'Homework'
|
|
for H in Homework.objects.filter(theme=theme.material):
|
|
if 'homeworks' not in materials:
|
|
materials['homeworks'] = {}
|
|
if theme.material.id not in materials['homeworks']:
|
|
materials['homeworks'][theme.material.id] = []
|
|
c2 = None
|
|
try:
|
|
hj, c2 = HomeworkJ.objects.get_or_create(student=journal.student, material=H)
|
|
except HomeworkJ.MultipleObjectsReturned:
|
|
hj = multiple_exclude(journal.student, H, _type='H')
|
|
if hj and (not hj.parent or hj.parent != theme):
|
|
hj.parent = theme
|
|
hj.save()
|
|
if c2:
|
|
journal.append_waiting(CourseMap.objects.get(token=hj.material.token))
|
|
materials['homeworks'][theme.material.id].append(hj)
|
|
# print H
|
|
# print '============ Закончил с домашними заданиями'
|
|
# print 'Exam'
|
|
for E in Exam.objects.filter(theme=theme.material):
|
|
if 'exam' not in materials:
|
|
materials['exam'] = {}
|
|
if theme.material.id not in materials['exam']:
|
|
materials['exam'][theme.material.id] = []
|
|
try:
|
|
ej, c2 = ExamJ.objects.get_or_create(student=journal.student, material=E)
|
|
except ExamJ.MultipleObjectsReturned:
|
|
ej = multiple_exclude(journal.student, E, _type='E')
|
|
if ej and (not ej.parent or ej.parent != theme):
|
|
ej.parent = theme
|
|
ej.save()
|
|
materials['exam'][theme.material.id].append(ej)
|
|
# print E
|
|
# print '============ Закончил с экзаменами'
|
|
# print 'Lesson'
|
|
for L in Lesson.objects.filter(theme=theme.material):
|
|
if 'lessons' not in materials:
|
|
materials['lessons'] = {}
|
|
if theme.material.id not in materials['lessons']:
|
|
materials['lessons'][theme.material.id] = []
|
|
try:
|
|
lj, c2 = LessonJ.objects.get_or_create(student=journal.student, material=L)
|
|
except LessonJ.MultipleObjectsReturned:
|
|
lj = multiple_exclude(journal.student, L, _type='L')
|
|
if lj and (not lj.parent or lj.parent != theme):
|
|
lj.parent = theme
|
|
lj.save()
|
|
if c2:
|
|
journal.append_waiting(CourseMap.objects.get(token=lj.material.token))
|
|
materials['lessons'][theme.material.id].append(lj)
|
|
# print L
|
|
# print '============ Закончил с Уроками'
|
|
return True
|
|
|
|
|
|
def set_opened(journal, point):
|
|
# Запомнить открытие в журнал
|
|
journal.opens.add(CourseMap.objects.get(token=point))
|
|
journal.save()
|
|
run = True
|
|
for theme in CourseThemeJ.objects.filter(parent=journal):
|
|
if not run: break
|
|
for lesson in LessonJ.objects.filter(parent=theme):
|
|
if not run: break
|
|
s = False
|
|
if lesson.material.token == point: run = False
|
|
if not lesson.date: lesson.date = datetime.datetime.now();s = True
|
|
if not lesson.f_date and run: lesson.f_date = datetime.datetime.now();s = True
|
|
if not lesson.success and run: lesson.success = True;s = True
|
|
if s: lesson.save()
|
|
|
|
for homework in HomeworkJ.objects.filter(parent=theme):
|
|
if not run: break
|
|
s = False
|
|
if homework.material.token == point: run = False
|
|
if not homework.date: homework.date = datetime.datetime.now();s = True
|
|
if not homework.f_date and run: homework.f_date = datetime.datetime.now();s = True
|
|
if not homework.success and run: homework.success = True;s = True
|
|
if s: homework.save()
|
|
|
|
for exam in ExamJ.objects.filter(parent=theme):
|
|
if not run: break
|
|
s = False
|
|
if exam.material.token == point: run = False
|
|
if not exam.date: exam.date = datetime.datetime.now();s = True
|
|
if not exam.f_date and run: exam.f_date = datetime.datetime.now();s = True
|
|
if not exam.success and run: exam.success = True;s = True
|
|
if s: exam.save()
|
|
|
|
journal.reload_progress()
|
|
|
|
|
|
# Новое API
|
|
class Thread(models.Model):
|
|
subscribers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name=u'Подписчики')
|
|
|
|
|
|
class Journal(models.Model):
|
|
thread = models.ForeignKey(to=Thread, verbose_name=u'Тред')
|
|
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name=u'Инициатор действия')
|
|
content_type = models.ForeignKey(to=ContentType)
|
|
object_id = models.PositiveIntegerField()
|
|
content_object = GenericForeignKey('content_type', 'object_id')
|
|
action_type = models.ForeignKey(to=Action)
|
|
|
|
def __str__(self):
|
|
return 'Пользователь %s %s' % (self.user.email, self.action_type.name)
|
|
|
|
|
|
class Action(models.Model):
|
|
name = models.CharField(max_length=255, verbose_name=u'Наименование действия (на английском)')
|
|
text = models.TextField(verbose_name=u'Описание действия') |