feature/fix_generate_pass
Andrey 8 years ago
parent 07658205ac
commit 36af875ffb
  1. 24
      access/migrations/0002_auto_20171214_2034.py
  2. 28
      access/migrations/0003_auto_20171214_2049.py
  3. 35
      access/models/other.py
  4. 3
      access/models/user.py
  5. 7
      achievements/models.py
  6. 108
      course_service/courses/models.py
  7. 9
      course_service/maps/api.py
  8. 20
      course_service/maps/migrations/0002_auto_20171215_1329.py
  9. 76
      course_service/maps/models.py
  10. 18
      csv/load_bills.py
  11. 6
      csv/load_comments.py
  12. 17
      csv/load_courses.py
  13. 45
      csv/load_perm.py
  14. 11
      finance/signals.py
  15. 22
      storage/migrations/0003_comment_date.py
  16. 1
      storage/models.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-14 20:34
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('access', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='progress',
old_name='template',
new_name='route',
),
migrations.AlterUniqueTogether(
name='progress',
unique_together=set([('user', 'route')]),
),
]

@ -0,0 +1,28 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-14 20:49
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('access', '0002_auto_20171214_2034'),
]
operations = [
migrations.AlterField(
model_name='progress',
name='teacher',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию'),
),
migrations.AlterField(
model_name='progress',
name='user',
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'),
preserve_default=False,
),
]

@ -49,44 +49,17 @@ class Account(models.Model):
class Progress(models.Model):
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию",
related_name='teacher_progress')
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент', null=True)
template = models.CharField(max_length=15, verbose_name='Токен прохождения')
related_name='teacher_progress', null=True, blank=True)
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент')
route = models.CharField(max_length=15, verbose_name='Токен прохождения')
def __str__(self):
return '%s' % (self.user.email,)
@transaction_decorator
def add_vertex(self, vertex):
PivotProgressVertex.objects.create(
progress=self,
vertex=vertex,
)
self.progress_list.add(vertex)
parent = vertex.vertex_set.first() if vertex.vertex_set.all().exists() else None
if parent:
children_ids = self.progress_list.values_list('id', flat=True)
_flt = ~Q(id__in=children_ids)
if parent.children.filter(_flt).exists():
self.progress_list.add(parent)
def get_template(self):
return self.template if self.template else self.course.route
def is_finish(self):
return self.get_template().is_finish(self.user)
def get_objects_in_progress(self):
return self.get_template().get_active_objects(self.user)
def is_access(self, vertex):
return vertex in self.progress_list.all() or vertex in self.get_objects_in_progress()
class Meta:
verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "template"),)
unique_together = (("user", "route"),)
class PivotProgressVertex(models.Model):

@ -119,9 +119,6 @@ class User(AbstractBaseUser, PermissionsMixin):
def get_short_name(self):
return self.first_name
def get_thread(self):
Thread.objects.get(key="""user_%s""" % self.id,)
class Meta:
verbose_name = _('Пользователь')
verbose_name_plural = _('Пользователи')

@ -56,8 +56,11 @@ class Diploma(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL)
def __str__(self):
return 'Студенту %s за курс %s' % (self.user.username, self.template.course.title)
return 'Студенту %s за курс %s' % (
self.user.get_full_name(),
self.template.course.title if self.template else "не связан с курсом",
)
class Meta:
verbose_name = 'Диплом'
verbose_name_plural = 'Дипломы'
verbose_name_plural = 'Дипломы'

@ -90,59 +90,6 @@ class Course(models.Model):
def __str__(self):
return self.title
def get_maps(self, user):
return user.progress_set.get(course=self).get_template().get_maps()
def get_vertexes(self, vertex_type=None):
if vertex_type:
return self.vertex_set.filter(content_type__model=vertex_type, course=self)
return self.vertex_set.filter(course=self)
def get_statistic(self):
"""
Минималистичная статистика по уроку,
количество тем, уроков, домашек.
"""
return {
"topic_count": self.get_vertexes('topic').count(),
"tutorial_count": self.get_vertexes('tutorial').count(),
"task_count": self.get_vertexes('task').count(),
}
def get_first(self, vertex_model_list=None):
if vertex_model_list is None:
vertex_model_list = ['topic', 'tutorial', 'task']
else:
for i in vertex_model_list:
if i not in ['topic', 'tutorial', 'task']:
raise ValueError('undefined model: ' + i)
vertex = Vertex.objects.get(id=self.coursemap_set.get(sort=0).get_first())
if vertex.content_type.model in vertex_model_list:
return vertex
return vertex.get_next(vertex_model_list)
def get_last(self, vertex_model_list=None):
if vertex_model_list is None:
vertex_model_list = ['topic', 'tutorial', 'task']
else:
for i in vertex_model_list:
if i not in ['topic', 'tutorial', 'task']:
raise ValueError('undefined model: ' + i)
vertex = Vertex.objects.get(id=self.coursemap_set.get(sort=0).get_last())
if vertex.content_type.model in vertex_model_list:
return vertex
return vertex.get_previous(vertex_model_list)
objects = CourseManager()
class Meta:
@ -180,61 +127,6 @@ class Vertex(models.Model):
def __str__(self):
return self.title
def get_next(self, route):
return route.get_first().get_next(self)
def get_previous(self, vertex_model_list=None):
if vertex_model_list is None:
vertex_model_list = ['topic', 'tutorial', 'task']
else:
for i in vertex_model_list:
if i not in ['topic', 'tutorial', 'task']:
raise ValueError('undefined model: ' + i)
vertex_id = CourseMap.objects.get(course=self.course).get_previous(self.id)
vertex = Vertex.objects.get(id=int(vertex_id), )
if vertex.content_type.model in vertex_model_list:
return vertex
return vertex.get_previous(vertex_model_list)
def is_more(self, vertex) -> bool:
if not self.course == vertex.course:
raise ValueError('Vertexes of different course')
course_map = CourseMap.objects.get(course=self.course)
return course_map.map_to_list().index(self.id) > course_map.map_to_list().index(vertex.id)
def check_vertex(self, user) -> bool:
if self.free:
return True
if not user.is_authenticated:
return False
try:
progress = self.course.progress_set.get(user=user)
except ObjectDoesNotExist:
return False
return progress.is_access(self)
def get_number(self, vertex_type=None):
"""
Возврощает порядковый номер узла с определённым типом.
Пример мы хотим определит какой по счёту теме принадлежит конкретно взятый урок.
"""
vertex_list = list(self.course.get_vertexes(vertex_type))
try:
res = vertex_list.index(self)
except ValueError:
parents = self.vertex_set.all()
if parents.count() == 1:
res = vertex_list.index(parents[0])
else:
res = None
return res
class Meta:
verbose_name = "Урок"
verbose_name_plural = "Уроки"

@ -5,3 +5,12 @@ class OutApiRoute:
@staticmethod
def change_id(id: int) -> str:
return CourseRoute.objects.get(id=id).out_key
@staticmethod
def get_route_matrix(out_key):
map_list = [i.map_course for i in CourseRoute.objects.get(out_key=out_key).pivotcoursemap_set.all()]
return [[j.vertex.token for j in i.pivotvertex_set.all()] for i in map_list]
@staticmethod
def get_route(out_key):
return CourseRoute.objects.get(out_key=out_key)

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-15 13:29
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('courses', '0003_auto_20171214_1513'),
('maps', '0001_initial'),
]
operations = [
migrations.AlterUniqueTogether(
name='coursemap',
unique_together=set([('course', 'name')]),
),
]

@ -13,19 +13,6 @@ class CourseRoute(models.Model):
name = models.CharField(max_length=255, verbose_name='Имя шаблона', blank=True, null=True)
is_template = models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')
def is_finish(self, user):
return len([1 for i in self.pivotcoursemap_set.all() if i.map_course.is_finish(user)]) > 0
def get_active_objects(self, user):
return (i.map_course.get_active_object(user) for i in self.pivotcoursemap_set.all()) \
if not self.is_finish(user) else []
def get_maps(self):
return (i.map_course for i in self.pivotcoursemap_set.all())
def get_first(self):
return self.pivotcoursemap_set.first().map_course
def __str__(self):
return self.name
@ -41,74 +28,13 @@ class CourseMap(models.Model):
course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан')
name = models.CharField(max_length=255, verbose_name="Имя прохождения", default="Линейное прохождение")
def get_next(self, vertex):
pivot = self.pivotvertex_set.get(vertex=vertex)
pivots = self.pivotvertex_set.filter(sort__gt=pivot.sort).exclude(vertex__content_type__model='topic')
return pivots.first().vertex if pivots.exists() else None
@transaction_decorator
def add_vertex(self, vertex, sort):
if sort > self.pivotvertex_set.count() + 1:
raise ValueError("list index out of range")
for i in self.pivotvertex_set.filter(sort__gte=sort):
i.sort += 1
i.save()
pivot = PivotVertex.objects.create(vertex=vertex, sort=sort, map_course=self)
pivot.save()
return pivot
def get_objects(self, vertex=None):
if vertex and not self.course == vertex.course:
raise MapTypeError('''Переданный узел принадлежит курсу "%s", а должен принадлежать курсу "%s"'''
% (self.course.title, vertex.course.title))
full_list = [i.vertex for i in self.pivotvertex_set.all()]
if vertex:
idx = full_list.index(vertex) + 1
return full_list[:idx]
return full_list
def get_tree(self, serializer=None):
from course_service.courses.serializers import MiniVertexSerializer
serializer = serializer if serializer is not None else MiniVertexSerializer
def helper(v_list):
new_list = []
for i in v_list:
val = serializer(i).data
new_list.append(val)
if i.children.all().count():
val['children'] = helper(i.children.all())
return new_list
return helper([i.vertex for i in self.pivotvertex_set.filter(vertex__vertex__isnull=True)])
def get_difference(self, user) -> list:
success_list = user.progress_set.get(course=self.course).progress_list.all()
all_vertex = [i.vertex for i in self.pivotvertex_set.all()]
res = list(set(all_vertex).difference(set(success_list)))
return res
def is_finish(self, user) -> bool:
return self.get_difference(user) == []
def get_active_object(self, user):
try:
return self.pivotvertex_set.exclude(
vertex__content_type__model='topic'
).filter(vertex__in=self.get_difference(user)).first().vertex
except AttributeError:
return None
def __str__(self):
return '''Линейное прохождение по курсу "%s"''' % self.course.title
class Meta:
verbose_name = 'Карта линейного прохождения курсов'
verbose_name_plural = 'Карты линейного прохождения курсов'
unique_together =('course', 'name',)
class PivotCourseMap(models.Model):

@ -12,10 +12,13 @@ django.setup()
from yandex_money.models import Payment
from finance.models import Bill, Invoice
from access.models.other import Progress
from course_service.courses.models import Course
if __name__ == '__main__':
Payment.objects.all().delete()
Bill.objects.all().delete()
Progress.objects.all().delete()
with open('./finance/bill.csv') as bill_csv:
bill_reader = csv.DictReader(bill_csv)
for row in bill_reader:
@ -54,20 +57,19 @@ if __name__ == '__main__':
real_price = None
inv = Invoice.objects.create(bill=bill, method=method, price=price, real_price=real_price, **row)
inv.date = row['date']
inv.save()
if method == 'Y':
yandex_pay, _is_create = Payment.objects.get_or_create(
if method == 'Y' and not row['status'] == 'W':
row['yandex_pay'], _is_create = Payment.objects.get_or_create(
order_amount=price,
order_number=inv.id,
customer_number=bill.user.id,
user=bill.user,
cps_email=bill.user.email,
shop_amount=inv.real_price,
shop_amount=real_price,
status='Processed' if 'P' else ('Success' if 'F' else 'Fail')
)
inv.yandex_pay = yandex_pay
inv.date = row['date']
inv.save()
except IntegrityError:
pass
pass

@ -10,13 +10,11 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup()
from course_service.courses.models import Vertex
from django.contrib.contenttypes.models import ContentType
from journals.models import Thread, Journal
from storage.models import File
from storage.models import Comment
from access.models.other import PivotProgressVertex
if __name__ == '__main__':
csv.field_size_limit(500 * 1024 * 1024)
ct = ContentType.objects.get(app_label='courses', model='vertex')
with open('./management/comment.csv') as comment_csv:
comment_reader = csv.DictReader(comment_csv)
for row in comment_reader:

@ -52,7 +52,6 @@ if __name__ == '__main__':
with open('./course/vertex.csv') as vertex_csv:
vertex_reader = csv.DictReader(vertex_csv)
sort = 0
for row in vertex_reader:
row = dict(row)
model_type = row.pop('type', None)
@ -69,6 +68,7 @@ if __name__ == '__main__':
if model_type == 'topic':
course = Course.objects.get(id=row.pop('course', None))
map_obj = CourseMap.objects.get(course=course)
Topic.objects.create(
id=pk,
icon=row.pop('icon', None),
@ -79,6 +79,7 @@ if __name__ == '__main__':
try:
topic_id = row.pop('topic', None)
last_pivot = PivotVertex.objects.filter(map_course=map_obj).last()
if model_type == 'tutorial':
topic = Topic.objects.get(id=topic_id)
small_vertex = Vertex.objects.create(
@ -90,8 +91,11 @@ if __name__ == '__main__':
title=title,
token=''.join(random.choice(string.ascii_letters) for x in range(15))
)
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
sort += 1
PivotVertex.objects.create(
map_course=map_obj,
vertex=small_vertex,
sort=last_pivot.sort+1 if last_pivot else 1,
)
if model_type == 'task':
topic = Topic.objects.get(id=topic_id)
@ -104,7 +108,10 @@ if __name__ == '__main__':
valid_type=1,
token=''.join(random.choice(string.ascii_letters) for x in range(15))
)
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
sort += 1
PivotVertex.objects.create(
map_course=map_obj,
vertex=small_vertex,
sort=last_pivot.sort+1 if last_pivot else 1,
)
except Topic.DoesNotExist:
pass

@ -9,53 +9,60 @@ django.setup()
from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model
from access.models.other import Progress
from access.models.other import Progress, PivotProgressVertex
from course_service.courses.models import Vertex, Course
from course_service.maps.api import OutApiRoute
if __name__ == '__main__':
Progress.objects.all().delete()
with open('./access/progress.csv') as progress_csv:
progress_reader = csv.DictReader(progress_csv)
for row in progress_reader:
course = Course.objects.get(id=row['course'])
route = Course.objects.get(id=row['course']).route.out_key
vertex = None
try:
pk=None
if row['type'] == 'lesson':
get_id = int(row['last_success_obj']) + 500
vertex = Vertex.objects.get(content_type__model='tutorial', object_id=row['last_success_obj'],
course=course)
pk = int(row['last_success_obj']) + 600
elif row['type'] == 'homework':
get_id = int(row['last_success_obj']) +50
vertex = Vertex.objects.get(content_type__model='task', object_id=row['last_success_obj'],
course=course)
pk = int(row['last_success_obj']) + 50
elif row['type'] == 'exam':
get_id = int(row['last_success_obj'])
vertex = Vertex.objects.get(content_type__model='task', object_id=str(get_id), course=course)
pk = int(row['last_success_obj'])
vertex = Vertex.objects.get(id=pk).token
except Vertex.DoesNotExist:
pass
api = OutApiRoute
list_vertex = OutApiRoute.get_route_matrix(route)[0]
try:
user = get_user_model().objects.get(id=row['user'])
if vertex is not None:
user = get_user_model().objects.get(id=row['user'])
p, c = Progress.objects.get_or_create(
user=user,
course=course,
route=route,
)
obj_list = list(course.route.get_maps())[0].get_objects(vertex)
g = Group.objects.get(name='students')
g.user_set.add(user)
if c:
p.progress_list.add(*obj_list)
for i in list_vertex:
PivotProgressVertex(
progress=p,
vertex=i,
status=2,
)
else:
p, c = Progress.objects.get_or_create(
user=get_user_model().objects.get(id=row['user']),
course=course,
user=user,
route=route,
)
g = Group.objects.get(name='students')
g.user_set.add(user)
except get_user_model().DoesNotExist:
print(row['user'])

@ -5,6 +5,9 @@ from yandex_money.models import Payment
from finance.models import Invoice
from access.models.other import Progress
from course_service.maps.api import OutApiRoute
api = OutApiRoute
@receiver(pre_save, sender=Invoice)
@ -25,16 +28,16 @@ def invoice_signal(instance, **kwargs):
if instance.status == 'F':
if instance.is_open:
Progress.objects.get_or_create(
template=instance.bill.route,
route=instance.bill.route,
user=instance.bill.user,
)
msg = EmailMessage(
'Ваш платёж прошёл успешно',
'''Вам открыт доступ к курсу "%s", вы можете перейти по ссылке и
ознакомиться с материалами https://go.skillbox.ru/course/%s'''
% (instance.bill.course.title, instance.bill.course.slug),
% (api.get_route(instance.bill.route).name, api.get_route(instance.bill.route).course.slug),
'robo@skillbox.ru',
[instance.yandex_pay.cps_email],
[instance.bill.user.email],
cc=[instance.bill.opener.email],
reply_to=[instance.bill.opener.email],
)
@ -57,7 +60,7 @@ def invoice_signal(instance, **kwargs):
решить проблему самостоятельно, ответьте на это письмо,
постарайтесь подробно описать последовательность действий,
которая привела к ошибке"""
% (instance.bill.user.get_full_name(), instance.bill.route.title, instance.id),
% (instance.bill.user.get_full_name(), api.get_route(instance.bill.route).course.title, instance.id),
instance.bill.opener.email,
reply_to=["it@skillbox.ru"]
)

@ -0,0 +1,22 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-15 15:32
from __future__ import unicode_literals
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('storage', '0002_auto_20171214_1908'),
]
operations = [
migrations.AddField(
model_name='comment',
name='date',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now, verbose_name='Дата коментария'),
preserve_default=False,
),
]

@ -39,6 +39,7 @@ class Comment(models.Model):
text = models.TextField(default="", verbose_name="Текст комментария")
files = models.ManyToManyField(to=File, blank=True, verbose_name='Файлы')
key = models.SlugField(unique=True, verbose_name="Получения комментария по ключу")
date = models.DateTimeField(auto_now_add=True, verbose_name="Дата коментария")
def __str__(self):
return '%s' % self.key

Loading…
Cancel
Save