зависимости

feature/fix_generate_pass
Andrey 8 years ago
parent b9fc5a8cef
commit 85d182e756
  1. 7
      access/admin.py
  2. 74
      access/migrations/0001_initial.py
  3. 21
      access/migrations/0002_auto_20171217_1808.py
  4. 26
      access/migrations/0002_init_group.py
  5. 20
      access/migrations/0003_pivotprogressvertex_date.py
  6. 21
      access/migrations/0004_auto_20171218_1438.py
  7. 20
      access/migrations/0005_auto_20171218_1516.py
  8. 20
      access/migrations/0006_auto_20171220_1228.py
  9. 21
      access/migrations/0007_progress_course.py
  10. 20
      access/migrations/0008_auto_20171220_1325.py
  11. 41
      access/models/other.py
  12. 0
      access/models/progress.py
  13. 4
      access/models/user.py
  14. 14
      access/serializers.py
  15. 12
      access/views.py
  16. 6
      achievements/admin.py
  17. 42
      achievements/migrations/0001_initial.py
  18. 10
      achievements/models.py
  19. 4
      achievements/serialers.py
  20. 2
      api_v1/urls.py
  21. 1
      course_service/courses/__init__.py
  22. 7
      course_service/courses/admin.py
  23. 71
      course_service/courses/migrations/0001_initial.py
  24. 24
      course_service/courses/migrations/0002_course_route.py
  25. 20
      course_service/courses/migrations/0003_auto_20171217_1821.py
  26. 11
      course_service/courses/signals.py
  27. 0
      course_service/maps/__init__.py
  28. 8
      course_service/maps/admin.py
  29. 16
      course_service/maps/api.py
  30. 7
      course_service/maps/apps.py
  31. 2
      course_service/maps/exeptions.py
  32. 83
      course_service/maps/migrations/0001_initial.py
  33. 0
      course_service/maps/migrations/__init__.py
  34. 67
      course_service/maps/models.py
  35. 27
      course_service/maps/serializers.py
  36. 23
      course_service/maps/tests.py
  37. 3
      course_service/maps/views.py
  38. 1
      courses/__init__.py
  39. 9
      courses/admin.py
  40. 2
      courses/api.py
  41. 2
      courses/apps.py
  42. 127
      courses/migrations/0001_initial.py
  43. 42
      courses/migrations/0002_init_demands.py
  44. 0
      courses/migrations/__init__.py
  45. 79
      courses/models.py
  46. 12
      courses/serializers.py
  47. 4
      courses/tsets.py
  48. 2
      courses/urls.py
  49. 8
      courses/views.py
  50. 2
      csv/load_bills.py
  51. 1
      csv/load_comments.py
  52. 14
      csv/load_courses.py
  53. 8
      csv/load_diploma.py
  54. 12
      csv/load_perm.py
  55. 5
      csv/load_users.py
  56. 6
      finance/migrations/0001_initial.py
  57. 20
      finance/migrations/0002_auto_20171225_1142.py
  58. 2
      finance/models.py
  59. 2
      library/migrations/0001_initial.py
  60. 3
      lms/settings.py
  61. 1
      requirements.txt
  62. 2
      storage/migrations/0001_initial.py

@ -1,9 +1,12 @@
from django.contrib import admin from django.contrib import admin
from access.models.other import Invite, Account, Progress, ResetPassword from access.models.other import Invite, Account, Progress, ResetPassword, ProgressLesson, UserAnswer, UserAnswerBlock
from access.models.user import User from access.models.user import User
admin.site.register(User) admin.site.register(User)
admin.site.register(Account) admin.site.register(Account)
admin.site.register(Progress) admin.site.register(Progress)
admin.site.register(Invite) admin.site.register(Invite)
admin.site.register(ResetPassword) admin.site.register(ResetPassword)
admin.site.register(ProgressLesson)
admin.site.register(UserAnswer)
admin.site.register(UserAnswerBlock)

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03 # Generated by Django 1.11.6 on 2018-01-11 13:07
from __future__ import unicode_literals from __future__ import unicode_literals
import access.models.user import access.models.user
@ -8,6 +8,7 @@ import django.contrib.postgres.fields
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
import phonenumber_field.modelfields import phonenumber_field.modelfields
import uuid
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -22,11 +23,10 @@ class Migration(migrations.Migration):
migrations.CreateModel( migrations.CreateModel(
name='User', name='User',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')), ('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')), ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')), ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('out_key', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Ключ для внешних сервисов')), ('out_key', models.UUIDField(default=uuid.uuid4, editable=False, primary_key=True, serialize=False, verbose_name='Токен')),
('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')), ('email', models.EmailField(max_length=254, unique=True, verbose_name='email address')),
('first_name', models.CharField(blank=True, default='Гость', max_length=63, verbose_name='first name')), ('first_name', models.CharField(blank=True, default='Гость', max_length=63, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=63, verbose_name='last name')), ('last_name', models.CharField(blank=True, max_length=63, verbose_name='last name')),
@ -53,7 +53,7 @@ class Migration(migrations.Migration):
('city', models.CharField(blank=True, max_length=63, null=True)), ('city', models.CharField(blank=True, max_length=63, null=True)),
('gender', models.SmallIntegerField(choices=[(0, 'undefined'), (1, 'male'), (2, 'female')], default=0)), ('gender', models.SmallIntegerField(choices=[(0, 'undefined'), (1, 'male'), (2, 'female')], default=0)),
('photo', models.ImageField(default='/static/default/access/default.png', upload_to='user/photo/')), ('photo', models.ImageField(default='/static/default/access/default.png', upload_to='user/photo/')),
('phone', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128)), ('phone', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True)),
('owner', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ('owner', models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
@ -73,20 +73,13 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Приглошения в систему', 'verbose_name_plural': 'Приглошения в систему',
}, },
), ),
migrations.CreateModel(
name='PivotProgressVertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('vertex', models.CharField(blank=True, max_length=15, unique=True, verbose_name='Ссылки на узлы')),
('status', models.SmallIntegerField(choices=[(2, 'Выполненно'), (1, 'Ожидание'), (0, 'Не выполненно')], default=0)),
('comment', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, unique=True, verbose_name='Ссылки на комменты'), size=None)),
],
),
migrations.CreateModel( migrations.CreateModel(
name='Progress', name='Progress',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('route', models.CharField(max_length=15, verbose_name='Токен прохождения')), ('lessons', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=15, unique=True, verbose_name='Ссылки на скрытые уроки'), default=[], size=None)),
('route', models.CharField(blank=True, max_length=15, null=True, verbose_name='Токен прохождения')),
('course', models.CharField(max_length=127, verbose_name='Слаг курса')),
('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию')), ('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент')),
], ],
@ -95,6 +88,48 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Прогресс пользователя', 'verbose_name_plural': 'Прогресс пользователя',
}, },
), ),
migrations.CreateModel(
name='ProgressLesson',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lesson', models.CharField(blank=True, max_length=15, verbose_name='Ссылка на узлы')),
('comment', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=15, unique=True, verbose_name='Ссылки на комменты'), default=[], size=None)),
('date', models.DateTimeField(blank=True, null=True, verbose_name='Дата зачтения задания')),
('progress', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='access.Progress')),
('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь')),
],
options={
'verbose_name': 'Прохождение уроков',
'verbose_name_plural': 'Прохождение урока',
},
),
migrations.CreateModel(
name='UserAnswer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('key', models.CharField(blank=True, max_length=255, verbose_name='Наименование поля')),
('value', models.TextField(verbose_name='Значение в поле')),
('status', models.CharField(choices=[('done', 'done'), ('wait', 'wait'), ('fail', 'fail')], default='done', max_length=20)),
],
options={
'verbose_name': 'Ответ пользователя',
'verbose_name_plural': 'Ответы пользователя',
},
),
migrations.CreateModel(
name='UserAnswerBlock',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now_add=True, verbose_name='Дата сдачи')),
('demand', models.CharField(blank=True, max_length=15, verbose_name='Ссылка на правило')),
('checker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Проверяющий')),
('progress', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='access.ProgressLesson')),
],
options={
'verbose_name': 'Блок ответов пользователя',
'verbose_name_plural': 'Блоки ответов пользователя',
},
),
migrations.CreateModel( migrations.CreateModel(
name='ResetPassword', name='ResetPassword',
fields=[ fields=[
@ -108,14 +143,9 @@ class Migration(migrations.Migration):
bases=('access.invite',), bases=('access.invite',),
), ),
migrations.AddField( migrations.AddField(
model_name='pivotprogressvertex', model_name='useranswer',
name='progress', name='block',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='access.Progress'), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='access.UserAnswerBlock'),
),
migrations.AddField(
model_name='pivotprogressvertex',
name='teacher',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь'),
), ),
migrations.AddField( migrations.AddField(
model_name='invite', model_name='invite',

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:08
from __future__ import unicode_literals
from django.db import migrations
import phonenumber_field.modelfields
class Migration(migrations.Migration):
dependencies = [
('access', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='account',
name='phone',
field=phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True),
),
]

@ -1,14 +1,11 @@
import os, sys, django from __future__ import unicode_literals
sys.path.append("../") from django.contrib.auth.models import Group
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup()
# TODO переместить в миграции from django.db import migrations
from django.contrib.auth.models import Group
if __name__ == '__main__': def init_group(*_args, **_kwargs):
Group.objects.get_or_create(name='admin') Group.objects.get_or_create(name='admin')
Group.objects.get_or_create(name='students') Group.objects.get_or_create(name='students')
Group.objects.get_or_create(name='teachers') Group.objects.get_or_create(name='teachers')
@ -18,4 +15,17 @@ if __name__ == '__main__':
Group.objects.get_or_create(name='partners') Group.objects.get_or_create(name='partners')
Group.objects.get_or_create(name='supports') Group.objects.get_or_create(name='supports')
Group.objects.get_or_create(name='finance') Group.objects.get_or_create(name='finance')
Group.objects.get_or_create(name='project_managers') Group.objects.get_or_create(name='project_managers')
class Migration(migrations.Migration):
initial = True
dependencies = [
('access', '0001_initial'),
]
operations = [
migrations.RunPython(init_group)
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-18 14:37
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0002_auto_20171217_1808'),
]
operations = [
migrations.AddField(
model_name='pivotprogressvertex',
name='date',
field=models.DateTimeField(blank=True, null=True, verbose_name='Дата зачтения задания'),
),
]

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-18 14:38
from __future__ import unicode_literals
import django.contrib.postgres.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0003_pivotprogressvertex_date'),
]
operations = [
migrations.AlterField(
model_name='pivotprogressvertex',
name='comment',
field=django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=15, unique=True, verbose_name='Ссылки на комменты'), default=[], size=None),
),
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-18 15:16
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0004_auto_20171218_1438'),
]
operations = [
migrations.AlterField(
model_name='pivotprogressvertex',
name='vertex',
field=models.CharField(blank=True, max_length=15, verbose_name='Ссылки на узлы'),
),
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-20 12:28
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0005_auto_20171218_1516'),
]
operations = [
migrations.AlterField(
model_name='progress',
name='route',
field=models.CharField(blank=True, max_length=15, null=True, verbose_name='Токен прохождения'),
),
]

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-20 13:21
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0006_auto_20171220_1228'),
]
operations = [
migrations.AddField(
model_name='progress',
name='course',
field=models.CharField(default='', max_length=15, verbose_name='Токен курса'),
preserve_default=False,
),
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-20 13:25
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('access', '0007_progress_course'),
]
operations = [
migrations.AlterField(
model_name='progress',
name='course',
field=models.CharField(max_length=127, verbose_name='Слаг курса'),
),
]

@ -1,6 +1,7 @@
from django.conf import settings from django.conf import settings
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.db import models from django.db import models
from model_utils import Choices
from phonenumber_field.modelfields import PhoneNumberField from phonenumber_field.modelfields import PhoneNumberField
@ -44,6 +45,8 @@ class Account(models.Model):
class Progress(models.Model): class Progress(models.Model):
lessons = ArrayField(
models.CharField(max_length=15, verbose_name='Ссылки на скрытые уроки', unique=True), default=[])
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='Студент')
@ -59,16 +62,36 @@ class Progress(models.Model):
unique_together = (("user", "route"),) unique_together = (("user", "route"),)
class PivotProgressVertex(models.Model): class ProgressLesson(models.Model):
# TODO переименовать в ProgressVertex
VERTEX_STATUS = (
(2, 'Выполненно'),
(1, 'Ожидание'),
(0, 'Не выполненно'),
) # TODO перейти на Choices из django-model-utils и сделать ключи строками done/wait/fail
progress = models.ForeignKey(to=Progress) progress = models.ForeignKey(to=Progress)
vertex = models.CharField(max_length=15, blank=True, verbose_name='Ссылки на узлы') lesson = models.CharField(max_length=15, blank=True, verbose_name='Ссылка на узлы')
status = models.SmallIntegerField(choices=VERTEX_STATUS, default=0)
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь",) teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь",)
comment = ArrayField(models.CharField(max_length=15, verbose_name='Ссылки на комменты', unique=True), default=[]) comment = ArrayField(models.CharField(max_length=15, verbose_name='Ссылки на комменты', unique=True), default=[])
date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True) date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True)
class Meta:
verbose_name = 'Прохождение уроков'
verbose_name_plural = 'Прохождение урока'
class UserAnswerBlock(models.Model):
progress = models.ForeignKey(to=ProgressLesson)
date = models.DateTimeField(verbose_name='Дата сдачи', auto_now_add=True)
demand = models.CharField(max_length=15, blank=True, verbose_name='Ссылка на правило')
checker = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Проверяющий",)
class Meta:
verbose_name = 'Блок ответов пользователя'
verbose_name_plural = 'Блоки ответов пользователя'
class UserAnswer(models.Model):
block = models.ForeignKey(to=UserAnswerBlock)
key = models.CharField(max_length=255, blank=True, verbose_name='Наименование поля')
value = models.TextField(verbose_name='Значение в поле')
STATUS = Choices('done', 'wait', 'fail')
status = models.CharField(choices=STATUS, default=STATUS.done, max_length=20)
class Meta:
verbose_name = 'Ответ пользователя'
verbose_name_plural = 'Ответы пользователя'

@ -1,5 +1,6 @@
import random import random
import string import string
import uuid
from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser
from django.contrib.auth.models import Group, PermissionsMixin from django.contrib.auth.models import Group, PermissionsMixin
@ -44,7 +45,6 @@ class CustomUserManager(BaseUserManager):
email = self.normalize_email(email) email = self.normalize_email(email)
user = self.model(email=email, is_staff=is_staff, is_active=is_active, first_name=first_name, user = self.model(email=email, is_staff=is_staff, is_active=is_active, first_name=first_name,
out_key=''.join(random.choice(string.ascii_letters) for x in range(15)),
is_superuser=is_superuser, date_joined=date_joined, last_login=last_login, **extra_fields) is_superuser=is_superuser, date_joined=date_joined, last_login=last_login, **extra_fields)
if not password: if not password:
@ -93,7 +93,7 @@ class CustomUserManager(BaseUserManager):
class User(AbstractBaseUser, PermissionsMixin): class User(AbstractBaseUser, PermissionsMixin):
out_key = models.CharField(max_length=15, unique=True, verbose_name="Ключ для внешних сервисов", editable=False) out_key = models.UUIDField(verbose_name="Токен", default=uuid.uuid4, primary_key=True, editable=False)
email = models.EmailField(_('email address'), unique=True) email = models.EmailField(_('email address'), unique=True)
first_name = models.CharField(_('first name'), max_length=63, blank=True, default='Гость') first_name = models.CharField(_('first name'), max_length=63, blank=True, default='Гость')
last_name = models.CharField(_('last name'), max_length=63, blank=True) last_name = models.CharField(_('last name'), max_length=63, blank=True)

@ -1,23 +1,17 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from access.models.other import Account, Progress, PivotProgressVertex from access.models.other import Account, Progress, ProgressLesson
from achievements.serialers import DiplomaSerializer, AchievementsSerializer from achievements.serialers import DiplomaSerializer, AchievementsSerializer
class PivotProgressSerializer(serializers.ModelSerializer): class ProgressVertexSerializer(serializers.ModelSerializer):
# TODO переименовать в ProgressVertexSerializer
status = serializers.SerializerMethodField()
teacher = serializers.SerializerMethodField() teacher = serializers.SerializerMethodField()
class Meta: class Meta:
model = PivotProgressVertex model = ProgressLesson
exclude = ('id', 'progress') exclude = ('id', 'progress')
@staticmethod
def get_status(self):
return self.get_status_display()
@staticmethod @staticmethod
def get_teacher(self): def get_teacher(self):
return self.teacher.get_full_name() return self.teacher.get_full_name()
@ -32,7 +26,7 @@ class ProgressSerializer(serializers.ModelSerializer):
@staticmethod @staticmethod
def get_vertexes(self): def get_vertexes(self):
return [PivotProgressSerializer(i).data for i in self.pivotprogressvertex_set.all()] return [ProgressVertexSerializer(i).data for i in self.progressvertex_set.all()]
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):

@ -12,8 +12,8 @@ from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from access.models.other import Invite, Progress, ResetPassword, PivotProgressVertex from access.models.other import Invite, Progress, ResetPassword, ProgressLesson
from access.serializers import UserSelfSerializer, UserSearchSerializer, PivotProgressSerializer from access.serializers import UserSelfSerializer, UserSearchSerializer, ProgressVertexSerializer
class TeacherListView(APIView): class TeacherListView(APIView):
@ -244,13 +244,13 @@ class UpdateProgress(APIView):
try: try:
p = Progress.objects.get(user=request.user, course=course) p = Progress.objects.get(user=request.user, course=course)
try: try:
pv = PivotProgressVertex.objects.get( pv = ProgressLesson.objects.get(
progress=p, progress=p,
vertex=token, vertex=token,
) )
except PivotProgressVertex.DoesNotExist: except ProgressLesson.DoesNotExist:
pv = PivotProgressVertex.objects.create( pv = ProgressLesson.objects.create(
date=datetime.datetime.now(), date=datetime.datetime.now(),
teacher=p.teacher, teacher=p.teacher,
progress=p, progress=p,
@ -258,7 +258,7 @@ class UpdateProgress(APIView):
) )
pv.status = 2 pv.status = 2
pv.save() pv.save()
return Response(PivotProgressSerializer(pv).data, status=200) return Response(ProgressVertexSerializer(pv).data, status=200)
except Progress.DoesNotExist: except Progress.DoesNotExist:
return Response('Не найден прогресс по заданным параметрам', status=404) return Response('Не найден прогресс по заданным параметрам', status=404)

@ -1,9 +1,9 @@
from django.contrib import admin from django.contrib import admin
from achievements.models import Skills, Achievements, SkillJ, DiplomaGen, Diploma from achievements.models import Skill, Achievement, SkillJ, DiplomaGen, Diploma
admin.site.register(Skills) admin.site.register(Skill)
admin.site.register(Achievements) admin.site.register(Achievement)
admin.site.register(SkillJ) admin.site.register(SkillJ)
admin.site.register(Diploma) admin.site.register(Diploma)
admin.site.register(DiplomaGen) admin.site.register(DiplomaGen)

@ -1,8 +1,10 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03 # Generated by Django 1.11.6 on 2018-01-11 10:47
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -10,15 +12,18 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('courses', '0001_initial'),
] ]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='Achievements', name='Achievement',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('img', models.ImageField(upload_to='achives', verbose_name='Отображение достижения')), ('img', models.ImageField(upload_to='achives', verbose_name='Отображение достижения')),
('text', models.CharField(max_length=255, verbose_name='Текст достижения')), ('text', models.CharField(max_length=255, verbose_name='Текст достижения')),
('users', models.ManyToManyField(to=settings.AUTH_USER_MODEL)),
], ],
options={ options={
'verbose_name': 'Достижение', 'verbose_name': 'Достижение',
@ -41,6 +46,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('template', models.URLField(verbose_name='Путь до шаблона')), ('template', models.URLField(verbose_name='Путь до шаблона')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course')),
], ],
options={ options={
'verbose_name': 'Генератор дипломов', 'verbose_name': 'Генератор дипломов',
@ -48,27 +54,39 @@ class Migration(migrations.Migration):
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='SkillJ', name='Skill',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Наименование')),
('color', models.CharField(max_length=255, verbose_name='Цвет')),
('icon', models.ImageField(help_text='65x65', upload_to='skills', verbose_name='Картинка')),
('description', models.TextField(blank=True, verbose_name='Описание')),
], ],
options={ options={
'verbose_name': 'Размер навыка', 'verbose_name': 'Навык',
'verbose_name_plural': 'Размеры навыков', 'verbose_name_plural': 'Навыки',
}, },
), ),
migrations.CreateModel( migrations.CreateModel(
name='Skills', name='SkillJ',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Наименование')), ('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Lesson', verbose_name='Урок')),
('color', models.CharField(max_length=255, verbose_name='Цвет')), ('skill', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='achievements.Skill', verbose_name='Навык')),
('icon', models.ImageField(help_text='65x65', upload_to='skills', verbose_name='Картинка')),
('description', models.TextField(blank=True, verbose_name='Описание')),
], ],
options={ options={
'verbose_name': 'Навык', 'verbose_name': 'Размер навыка',
'verbose_name_plural': 'Навыки', 'verbose_name_plural': 'Размеры навыков',
}, },
), ),
migrations.AddField(
model_name='diploma',
name='template',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='achievements.DiplomaGen', verbose_name='Использовать шаблон'),
),
migrations.AddField(
model_name='diploma',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
] ]

@ -1,10 +1,10 @@
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
from course_service.courses.models import Course, Vertex from courses.models import Course, Lesson
class Achievements(models.Model): class Achievement(models.Model):
img = models.ImageField(verbose_name='Отображение достижения', upload_to='achives') img = models.ImageField(verbose_name='Отображение достижения', upload_to='achives')
text = models.CharField(max_length=255, verbose_name="Текст достижения") text = models.CharField(max_length=255, verbose_name="Текст достижения")
users = models.ManyToManyField(to=settings.AUTH_USER_MODEL) users = models.ManyToManyField(to=settings.AUTH_USER_MODEL)
@ -14,7 +14,7 @@ class Achievements(models.Model):
verbose_name_plural = 'Достижения' verbose_name_plural = 'Достижения'
class Skills(models.Model): class Skill(models.Model):
title = models.CharField(verbose_name='Наименование', max_length=255) title = models.CharField(verbose_name='Наименование', max_length=255)
color = models.CharField(verbose_name='Цвет', max_length=255) color = models.CharField(verbose_name='Цвет', max_length=255)
icon = models.ImageField(verbose_name='Картинка', upload_to='skills', help_text='65x65') icon = models.ImageField(verbose_name='Картинка', upload_to='skills', help_text='65x65')
@ -28,8 +28,8 @@ class Skills(models.Model):
class SkillJ(models.Model): class SkillJ(models.Model):
skill = models.ForeignKey(to=Skills, verbose_name='Навык') skill = models.ForeignKey(to=Skill, verbose_name='Навык')
lesson = models.ForeignKey(to=Vertex, verbose_name='Урок') lesson = models.ForeignKey(to=Lesson, verbose_name='Урок')
def __str__(self): return '%s' % self.skill def __str__(self): return '%s' % self.skill

@ -1,5 +1,5 @@
from rest_framework import serializers from rest_framework import serializers
from achievements.models import Diploma, Achievements from achievements.models import Diploma, Achievement
class DiplomaSerializer(serializers.ModelSerializer): class DiplomaSerializer(serializers.ModelSerializer):
@ -12,5 +12,5 @@ class DiplomaSerializer(serializers.ModelSerializer):
class AchievementsSerializer(serializers.ModelSerializer): class AchievementsSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Achievements model = Achievement
fields = ('img', 'text') fields = ('img', 'text')

@ -1,7 +1,7 @@
from django.conf.urls import url, include from django.conf.urls import url, include
urlpatterns = [ urlpatterns = [
url(r'courses/', include('course_service.courses.urls')), url(r'courses/', include('courses.urls')),
url(r'users/', include('access.urls')), url(r'users/', include('access.urls')),
url(r'library/', include('library.urls')), url(r'library/', include('library.urls')),
url(r'finance/', include('finance.urls')), url(r'finance/', include('finance.urls')),

@ -1 +0,0 @@
default_app_config = "course_service.courses.apps.CoursesAppConfig"

@ -1,7 +0,0 @@
from django.contrib import admin
from course_service.courses.models import Course, Topic, Vertex
admin.site.register(Topic)
admin.site.register(Vertex)
admin.site.register(Course)

@ -1,71 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03
from __future__ import unicode_literals
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Course',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('hidden', models.BooleanField(default=False, verbose_name='Видно только оплатившим')),
('level', models.CharField(choices=[('B', 'Базовый'), ('A', 'Продвинутый'), ('E', 'Экспертный'), ('B+A', 'Базовый + Продвинутый')], default='B', max_length=3, verbose_name='Уровень')),
('slug', models.SlugField(editable=False, unique=True)),
('direction', models.SmallIntegerField(choices=[(3, 'Бизнес'), (2, 'Веб-дизайн'), (1, 'Разработка'), (4, 'Рисование')], verbose_name='Направление')),
('public', models.BooleanField(default=False, verbose_name='Опубликовать')),
('title', models.CharField(max_length=255, unique=True, verbose_name='Заголовок')),
('description', models.TextField(blank=True, verbose_name='Описание')),
('image', models.URLField(blank=True, max_length=255, verbose_name='Изображение')),
('big_image', models.URLField(blank=True, max_length=255, verbose_name='Большое изображение')),
('big_mobile_image', models.URLField(blank=True, help_text='Большая картинка для мобильной версии', max_length=255, verbose_name='Под мобилку')),
('teachers', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Ссылки на преподов'), default=[], size=None)),
],
options={
'verbose_name': 'Курс',
'verbose_name_plural': 'Курсы',
},
),
migrations.CreateModel(
name='Topic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Название')),
('icon', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Иконка темы')),
('description', models.TextField(blank=True, null=True, verbose_name='Описание')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='курс')),
],
options={
'verbose_name': 'Тема',
'verbose_name_plural': 'Темы',
},
),
migrations.CreateModel(
name='Vertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Название')),
('free', models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться')),
('description', models.TextField(blank=True, null=True, verbose_name='Описание')),
('video', models.TextField(blank=True, null=True, verbose_name='Код видео')),
('materials', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Материалы урока'), size=None)),
('valid_type', models.SmallIntegerField(choices=[(3, 'Автаматическая валидация'), (2, 'Полуавтаматическая валидация'), (1, 'Ручная валидация'), (0, 'Без валидации')], default=0)),
('token', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Ключ доступа к узлу')),
('topic', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Topic', verbose_name='Тема')),
],
options={
'verbose_name': 'Урок',
'verbose_name_plural': 'Уроки',
},
),
]

@ -1,24 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('courses', '0001_initial'),
('maps', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='course',
name='route',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='Порядок прохождения по умолчанию'),
),
]

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:21
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('courses', '0002_course_route'),
]
operations = [
migrations.AlterField(
model_name='course',
name='slug',
field=models.SlugField(editable=False, max_length=127, unique=True),
),
]

@ -1,11 +0,0 @@
from django.db.models.signals import pre_delete
from django.dispatch import receiver
from course_service.courses.models import Vertex
@receiver(pre_delete, sender=Vertex)
def delete_dependencies(instance, **kwargs):
"""Удаляем зависимости вместе с узлом"""
if instance.content_object:
instance.content_object.delete()

@ -1,8 +0,0 @@
from django.contrib import admin
from course_service.maps.models import CourseMap, CourseRoute, PivotCourseMap, PivotVertex
admin.site.register(CourseMap)
admin.site.register(CourseRoute)
admin.site.register(PivotCourseMap)
admin.site.register(PivotVertex)

@ -1,16 +0,0 @@
from course_service.maps.models import CourseRoute
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)

@ -1,7 +0,0 @@
from django.apps import AppConfig
class MapsConfig(AppConfig):
name = "course_service.maps"
label = 'maps'
verbose_name = "Отображение курсов"

@ -1,2 +0,0 @@
class MapTypeError(ValueError):
pass

@ -1,83 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('courses', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='CourseMap',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='Имя прохождения')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='К какому курсу привязан')),
],
options={
'verbose_name': 'Карта линейного прохождения курсов',
'verbose_name_plural': 'Карты линейного прохождения курсов',
},
),
migrations.CreateModel(
name='CourseRoute',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('out_key', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Ключ для внешних сервисов')),
('name', models.CharField(max_length=255, verbose_name='Имя шаблона')),
('is_template', models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')),
],
options={
'verbose_name': 'Маршрут прохождения',
'verbose_name_plural': 'Маршруты прохождения',
},
),
migrations.CreateModel(
name='PivotCourseMap',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('sort', models.SmallIntegerField(verbose_name='Порядок сортировки')),
('map_course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортировке имеетотношение')),
('route', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='К какому узлу')),
],
options={
'verbose_name': 'Порядок сортировки маршрута',
'verbose_name_plural': 'Порядки сортировок маршрутов',
'ordering': ('sort',),
},
),
migrations.CreateModel(
name='PivotVertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('sort', models.SmallIntegerField(verbose_name='Порядок сортировки')),
('map_course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='maps.CourseMap', verbose_name='К какой сортировке имеетотношение')),
('vertex', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='К какому узлу')),
],
options={
'verbose_name': 'Порядок сортировки узла',
'verbose_name_plural': 'Порядки сортировок узла',
'ordering': ('sort',),
},
),
migrations.AlterUniqueTogether(
name='pivotvertex',
unique_together=set([('sort', 'map_course'), ('map_course', 'vertex')]),
),
migrations.AlterUniqueTogether(
name='pivotcoursemap',
unique_together=set([('sort', 'route'), ('map_course', 'route')]),
),
migrations.AlterUniqueTogether(
name='coursemap',
unique_together=set([('course', 'name')]),
),
]

@ -1,67 +0,0 @@
from django.db import models
from course_service.maps.exeptions import MapTypeError
from lms.global_decorators import transaction_decorator
class CourseRoute(models.Model):
"""
Объединение нескольких мап курса, одназначно
определяет способ прохождения по курсу.
"""
out_key = models.CharField(max_length=15, unique=True, verbose_name="Ключ для внешних сервисов", editable=False)
name = models.CharField(max_length=255, verbose_name='Имя шаблона')
is_template = models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')
def __str__(self):
return self.name
class Meta:
verbose_name = 'Маршрут прохождения'
verbose_name_plural = 'Маршруты прохождения'
class CourseMap(models.Model):
"""
Способы отображения курса. Упорядочены в порядке возрастания приоретета.
"""
course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан')
name = models.CharField(max_length=255, verbose_name="Имя прохождения")
def __str__(self):
return '''Линейное прохождение по курсу "%s"''' % self.course.title
class Meta:
verbose_name = 'Карта линейного прохождения курсов'
verbose_name_plural = 'Карты линейного прохождения курсов'
unique_together =('course', 'name',)
class PivotCourseMap(models.Model):
route = models.ForeignKey(to=CourseRoute, verbose_name="К какому узлу")
sort = models.SmallIntegerField(verbose_name='Порядок сортировки')
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортировке имеетотношение')
def __str__(self):
return '''Карта с №%s по маршруту ID%s''' % (self.sort, self.route_id)
class Meta:
verbose_name = 'Порядок сортировки маршрута'
verbose_name_plural = 'Порядки сортировок маршрутов'
unique_together = (('map_course', 'route'), ('sort', 'route'),)
ordering = ('sort',)
class PivotVertex(models.Model):
vertex = models.ForeignKey(to='courses.Vertex', verbose_name="К какому узлу")
sort = models.SmallIntegerField(verbose_name='Порядок сортировки')
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортировке имеетотношение')
def __str__(self):
return '''Карта с №%s по линейному прохождению ID%s''' % (self.sort, self.map_course_id)
class Meta:
verbose_name = 'Порядок сортировки узла'
verbose_name_plural = 'Порядки сортировок узла'
unique_together = (('map_course', 'vertex'), ('sort', 'map_course'))
ordering = ('sort',)

@ -1,27 +0,0 @@
from rest_framework import serializers
from course_service.maps.models import CourseRoute, CourseMap
class CourseRouteSerializer(serializers.ModelSerializer):
maps = serializers.SerializerMethodField()
class Meta:
model = CourseRoute
fields = ('maps', 'name')
@staticmethod
def get_maps(self):
return [CourseMapSerializer(i.map_course).data for i in self.pivotcoursemap_set.all()]
class CourseMapSerializer(serializers.ModelSerializer):
vertexes = serializers.SerializerMethodField()
class Meta:
model = CourseMap
fields = ('name', 'vertexes')
@staticmethod
def get_vertexes(self):
return [i.vertex.token for i in self.pivotvertex_set.all()]

@ -1,23 +0,0 @@
# from django.test import TestCase
# from course_service.maps.models import CourseRoute
#
# from course_service.maps.api import OutApiRoute
#
#
# class RouteOutApiTestCase(TestCase):
# def setUp(self):
# self.first_course = Course.objects.create(
# title='Первый курс',
# slug='perviy-kuourse',
# )
# self.CDTeacher = OutApiRoute()
#
# def test_teacher(self):
# token1 = "token1"
# token2 = "token2"
# token3 = "token3"
# self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token1)
# self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token2)
# self.CDTeacher.add_teacher(slug=self.first_course.slug, token=token3)
# self.CDTeacher.delete_teacher(slug=self.first_course.slug, token=token2)
# self.assertEqual(self.CDTeacher.get_token_list(self.first_course.slug), ['token1', 'token3'])

@ -1,3 +0,0 @@
from django.shortcuts import render
# Create your views here.

@ -0,0 +1 @@
default_app_config = "courses.apps.CoursesAppConfig"

@ -0,0 +1,9 @@
from django.contrib import admin
from courses.models import Course, Topic, Lesson, Demand, Field
admin.site.register(Topic)
admin.site.register(Lesson)
admin.site.register(Course)
admin.site.register(Demand)
admin.site.register(Field)

@ -1,4 +1,4 @@
from course_service.courses.models import Course from courses.models import Course
class InApiTeacher: class InApiTeacher:

@ -3,7 +3,7 @@ from django.apps import AppConfig
class CoursesAppConfig(AppConfig): class CoursesAppConfig(AppConfig):
name = "course_service.courses" name = "courses"
label = 'courses' label = 'courses'
verbose_name = "Курсы" verbose_name = "Курсы"

@ -0,0 +1,127 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-01-11 10:47
from __future__ import unicode_literals
import django.contrib.postgres.fields
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Course',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(editable=False, max_length=127, unique=True)),
('title', models.CharField(max_length=255, unique=True, verbose_name='Заголовок')),
('description', models.TextField(blank=True, verbose_name='Описание')),
('level', models.CharField(choices=[('B', 'Базовый'), ('A', 'Продвинутый'), ('E', 'Экспертный'), ('B+A', 'Базовый + Продвинутый')], default='B', max_length=3, verbose_name='Уровень')),
('direction', models.SmallIntegerField(choices=[(3, 'Бизнес'), (2, 'Веб-дизайн'), (1, 'Разработка'), (4, 'Рисование'), (5, 'Музыка')], verbose_name='Направление')),
('public', models.BooleanField(default=False, verbose_name='Опубликовать')),
('teachers', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Ссылки на преподов'), default=[], size=None)),
('image', models.URLField(blank=True, max_length=255, verbose_name='Изображение')),
('big_image', models.URLField(blank=True, max_length=255, verbose_name='Большое изображение')),
('big_mobile_image', models.URLField(blank=True, help_text='Большая картинка для мобильной версии', max_length=255, verbose_name='Под мобилку')),
('hidden', models.BooleanField(default=False, verbose_name='Видно только оплатившим')),
],
options={
'verbose_name': 'Курс',
'verbose_name_plural': 'Курсы',
},
),
migrations.CreateModel(
name='Demand',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.UUIDField(default=uuid.uuid4, editable=False, unique=True, verbose_name='Токен валидатора')),
('name', models.CharField(max_length=31, unique=True, verbose_name='Название')),
('checker', models.CharField(choices=[('student', 'student'), ('teacher', 'teacher'), ('support', 'support')], default='teacher', max_length=15, verbose_name='Проверяющий')),
('min_balls', models.SmallIntegerField(default=50, verbose_name='Проходной бал')),
],
options={
'verbose_name': 'Требования',
'verbose_name_plural': 'Требования',
},
),
migrations.CreateModel(
name='Field',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('label', models.CharField(max_length=255, verbose_name='Надпись у поля')),
('type', models.CharField(choices=[('text', 'text'), ('char', 'char'), ('boolean', 'boolean'), ('file', 'file')], default='char', max_length=20)),
('multiple', models.BooleanField(default=False)),
('null', models.BooleanField(default=False)),
('answers', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=255), blank=True, null=True, size=None)),
('balls', models.SmallIntegerField(default=100, verbose_name='Вознаграждение')),
('match', models.CharField(blank=True, max_length=255, null=True, verbose_name='Если не нулевое значение, то при точном сопоставлении даёт положителбный ответ')),
('demand', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Demand')),
],
options={
'verbose_name': 'Поле',
'verbose_name_plural': 'Поля',
},
),
migrations.CreateModel(
name='Lesson',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.CharField(editable=False, max_length=15, unique=True, verbose_name='Ключ доступа к узлу')),
('title', models.CharField(max_length=255, verbose_name='Название')),
('description', models.TextField(blank=True, null=True, verbose_name='Описание')),
('video', models.TextField(blank=True, null=True, verbose_name='Код видео')),
('material_tokens', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(blank=True, max_length=15, verbose_name='Материалы урока'), default=[], size=None)),
('free', models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться')),
('sort', models.SmallIntegerField(unique=True)),
],
options={
'verbose_name': 'Урок',
'verbose_name_plural': 'Уроки',
'ordering': ('sort',),
},
),
migrations.CreateModel(
name='LessonDemand',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('sort', models.SmallIntegerField(default=1)),
('demand', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Demand')),
('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Lesson')),
],
options={
'verbose_name': 'Порядок требований',
'verbose_name_plural': 'Порядок требований',
'ordering': ('sort',),
},
),
migrations.CreateModel(
name='Topic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=255, verbose_name='Название')),
('description', models.TextField(blank=True, null=True, verbose_name='Описание')),
('icon', models.ImageField(blank=True, null=True, upload_to='', verbose_name='Иконка темы')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='курс')),
],
options={
'verbose_name': 'Тема',
'verbose_name_plural': 'Темы',
},
),
migrations.AddField(
model_name='lesson',
name='topic',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Topic', verbose_name='Тема'),
),
migrations.AlterUniqueTogether(
name='lessondemand',
unique_together=set([('lesson', 'demand', 'sort')]),
),
]

@ -0,0 +1,42 @@
from __future__ import unicode_literals
from courses.models import Demand, Field
from django.db import migrations
def init_demands(*_args, **_kwargs):
d, c = Demand.objects.get_or_create(
min_balls=51,
name="Стандартные требования",
)
Field.objects.get_or_create(
demand=d,
label='Комментарий',
type='text',
null=True,
balls=50,
)
Field.objects.get_or_create(
demand=d,
label='Приложенные файлы',
type='files',
null=True,
multiple=True,
balls=50,
)
class Migration(migrations.Migration):
initial = True
dependencies = [
('courses', '0001_initial'),
]
operations = [
migrations.RunPython(init_demands)
]

@ -1,15 +1,13 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
import random import uuid
import string
import unidecode import unidecode
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.db import models from django.db import models
from django.template.defaultfilters import slugify from django.template.defaultfilters import slugify
from model_utils import Choices
from course_service.maps.models import CourseRoute, CourseMap
from lms.global_decorators import transaction_decorator
from lms.tools import decode_base64, get_real_name from lms.tools import decode_base64, get_real_name
COURSE_LEVEL = ( COURSE_LEVEL = (
@ -64,13 +62,6 @@ class CourseManager(models.Manager):
return course return course
def change_route(self, pk, route):
route = CourseRoute.objects.get(id=route)
course = self.get(id=pk)
course.route = route
course.save()
return course
class Course(models.Model): class Course(models.Model):
slug = models.SlugField(unique=True, editable=False, max_length=127) slug = models.SlugField(unique=True, editable=False, max_length=127)
@ -79,7 +70,6 @@ class Course(models.Model):
level = models.CharField(verbose_name='Уровень', choices=COURSE_LEVEL, default='B', max_length=3) level = models.CharField(verbose_name='Уровень', choices=COURSE_LEVEL, default='B', max_length=3)
direction = models.SmallIntegerField(choices=COURSE_DIRECTION, verbose_name='Направление') direction = models.SmallIntegerField(choices=COURSE_DIRECTION, verbose_name='Направление')
public = models.BooleanField(verbose_name='Опубликовать', default=False) public = models.BooleanField(verbose_name='Опубликовать', default=False)
route = models.OneToOneField(to=CourseRoute, verbose_name="Порядок прохождения по умолчанию", blank=True, null=True)
teachers = ArrayField( teachers = ArrayField(
models.CharField(max_length=15, blank=True, verbose_name='Ссылки на преподов'), default=[]) models.CharField(max_length=15, blank=True, verbose_name='Ссылки на преподов'), default=[])
image = models.URLField(verbose_name='Изображение', blank=True, max_length=255) image = models.URLField(verbose_name='Изображение', blank=True, max_length=255)
@ -115,25 +105,15 @@ class Topic(models.Model):
verbose_name_plural = "Темы" verbose_name_plural = "Темы"
class Vertex(models.Model): class Lesson(models.Model):
# TODO переименовать в Lesson
token = models.CharField(max_length=15, verbose_name="Ключ доступа к узлу", unique=True, editable=False) token = models.CharField(max_length=15, verbose_name="Ключ доступа к узлу", unique=True, editable=False)
topic = models.ForeignKey(to=Topic, verbose_name='Тема') topic = models.ForeignKey(to=Topic, verbose_name='Тема')
title = models.CharField(verbose_name='Название', max_length=255) title = models.CharField(verbose_name='Название', max_length=255)
description = models.TextField(verbose_name='Описание', blank=True, null=True) description = models.TextField(verbose_name='Описание', blank=True, null=True)
video = models.TextField(verbose_name='Код видео', blank=True, null=True) video = models.TextField(verbose_name='Код видео', blank=True, null=True)
materials = ArrayField(models.CharField(max_length=15, blank=True, verbose_name='Материалы урока')) material_tokens = ArrayField(models.CharField(max_length=15, blank=True, verbose_name='Материалы урока'), default=[])
# TODO material_tokens ???
free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться') free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться')
sort = models.SmallIntegerField(unique=True)
# TODO перейти на список валидаторов
VALID_TYPE = (
(3, 'Автаматическая валидация'),
(2, 'Полуавтаматическая валидация'),
(1, 'Ручная валидация'),
(0, 'Без валидации'),
)
valid_type = models.SmallIntegerField(choices=VALID_TYPE, default=0)
def __str__(self): def __str__(self):
return self.title return self.title
@ -141,3 +121,52 @@ class Vertex(models.Model):
class Meta: class Meta:
verbose_name = "Урок" verbose_name = "Урок"
verbose_name_plural = "Уроки" verbose_name_plural = "Уроки"
ordering = ('sort', )
class LessonDemand(models.Model):
demand = models.ForeignKey(to='Demand')
lesson = models.ForeignKey(to=Lesson)
sort = models.SmallIntegerField(default=1)
class Meta:
verbose_name = "Порядок требований"
verbose_name_plural = "Порядок требований"
ordering = ('sort', )
unique_together = ('lesson', 'demand', 'sort')
class Demand(models.Model):
CHECK_TYPES = Choices('student', 'teacher', 'support',)
token = models.UUIDField(verbose_name="Токен валидатора", default=uuid.uuid4, unique=True, editable=False)
name = models.CharField(max_length=31, verbose_name="Название", unique=True)
checker = models.CharField(
choices=CHECK_TYPES, default=CHECK_TYPES.teacher, max_length=15, verbose_name="Проверяющий",)
min_balls = models.SmallIntegerField(default=50, verbose_name='Проходной бал')
def __str__(self):
return self.name
class Meta:
verbose_name = "Требования"
verbose_name_plural = "Требования"
class Field(models.Model):
# TODO Нужно прикрутить предварительную валидацию
FIELD_TYPES = Choices('text', 'char', 'boolean', 'file')
demand = models.ForeignKey(to=Demand)
label = models.CharField(max_length=255, verbose_name='Надпись у поля')
type = models.CharField(choices=FIELD_TYPES, default=FIELD_TYPES.char, max_length=20)
multiple = models.BooleanField(default=False)
null = models.BooleanField(default=False)
answers = ArrayField(models.CharField(max_length=255), blank=True, null=True)
balls = models.SmallIntegerField(default=100, verbose_name='Вознаграждение')
match = models.CharField(
max_length=255,
verbose_name='Если не нулевое значение, то при точном сопоставлении даёт положителбный ответ',
blank=True, null=True)
class Meta:
verbose_name = "Поле"
verbose_name_plural = "Поля"

@ -1,7 +1,6 @@
from rest_framework import serializers from rest_framework import serializers
from course_service.courses.models import Course, Vertex, Topic from courses.models import Course, Lesson, Topic
from course_service.maps.serializers import CourseRouteSerializer
class TopicSerializer(serializers.ModelSerializer): class TopicSerializer(serializers.ModelSerializer):
@ -19,7 +18,7 @@ class TopicSerializer(serializers.ModelSerializer):
class MiniVertexSerializer(serializers.ModelSerializer): class MiniVertexSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = Vertex model = Lesson
fields = ('title', 'free', 'token') fields = ('title', 'free', 'token')
@ -27,7 +26,7 @@ class VertexSerializer(MiniVertexSerializer):
valid_type = serializers.SerializerMethodField() valid_type = serializers.SerializerMethodField()
class Meta: class Meta:
model = Vertex model = Lesson
exclude = ('id', 'topic', 'free') exclude = ('id', 'topic', 'free')
@staticmethod @staticmethod
@ -44,7 +43,6 @@ class CourseInitSerializer(serializers.ModelSerializer):
class CourseTreeSerializer(serializers.ModelSerializer): class CourseTreeSerializer(serializers.ModelSerializer):
tree = serializers.SerializerMethodField() tree = serializers.SerializerMethodField()
route = serializers.SerializerMethodField()
class Meta: class Meta:
model = Course model = Course
@ -54,10 +52,6 @@ class CourseTreeSerializer(serializers.ModelSerializer):
def get_tree(self): def get_tree(self):
return [TopicSerializer(i).data for i in self.topic_set.all()] return [TopicSerializer(i).data for i in self.topic_set.all()]
@staticmethod
def get_route(self):
return CourseRouteSerializer(self.route).data
class CourseDetailSerializer(serializers.ModelSerializer): class CourseDetailSerializer(serializers.ModelSerializer):
level = serializers.SerializerMethodField() level = serializers.SerializerMethodField()

@ -1,8 +1,8 @@
from django.test import TestCase from django.test import TestCase
from course_service.courses.models import Course from courses.models import Course
from lms.tools import EXAMPLE_BASE64 from lms.tools import EXAMPLE_BASE64
from course_service.courses.api import InApiTeacher from courses.api import InApiTeacher
class CourseInApiTestCase(TestCase): class CourseInApiTestCase(TestCase):

@ -1,6 +1,6 @@
from django.conf.urls import url from django.conf.urls import url
from course_service.courses import views as views from courses import views as views
urlpatterns = [ urlpatterns = [
url(r'vertex/(?P<token>.+)/$', views.VertexDetail.as_view()), url(r'vertex/(?P<token>.+)/$', views.VertexDetail.as_view()),

@ -1,9 +1,9 @@
from course_service.courses.models import Course, Vertex from courses.models import Course, Lesson
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from course_service.courses.serializers import CourseDetailSerializer, CourseTreeSerializer, VertexSerializer from courses.serializers import CourseDetailSerializer, CourseTreeSerializer, VertexSerializer
class TreeView(APIView): class TreeView(APIView):
@ -39,8 +39,8 @@ class VertexDetail(APIView):
def get(request, token): def get(request, token):
try: try:
vertex = Vertex.objects.get(token=token) vertex = Lesson.objects.get(token=token)
except Vertex.DoesNotExist: except Lesson.DoesNotExist:
return Response("Vertex doesn't exist", status=404) return Response("Vertex doesn't exist", status=404)
# if not vertex.check_vertex(request.user): # if not vertex.check_vertex(request.user):

@ -16,7 +16,7 @@ django.setup()
from yandex_money.models import Payment from yandex_money.models import Payment
from finance.models import Bill, Invoice from finance.models import Bill, Invoice
from access.models.other import Progress from access.models.other import Progress
from course_service.courses.models import Course from courses.models import Course
if __name__ == '__main__': if __name__ == '__main__':
Payment.objects.all().delete() Payment.objects.all().delete()

@ -6,7 +6,6 @@ import django
import os import os
import sys import sys
from django.contrib.auth import get_user_model
from django.db import IntegrityError from django.db import IntegrityError
sys.path.append("../") sys.path.append("../")

@ -10,18 +10,12 @@ sys.path.append("../")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup() django.setup()
from course_service.courses.api import InApiTeacher from courses.api import InApiTeacher
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from course_service.courses.models import Course, Vertex, Topic from courses.models import Course, Lesson, Topic
from course_service.maps.models import CourseRoute, CourseMap, PivotVertex, PivotCourseMap
from storage.models import File from storage.models import File
if __name__ == '__main__': if __name__ == '__main__':
CourseMap.objects.all().delete()
CourseRoute.objects.all().delete()
PivotVertex.objects.all().delete()
PivotCourseMap.objects.all().delete()
Vertex.objects.all().delete()
Course.objects.all().delete() Course.objects.all().delete()
with open('./course/course.csv') as user_csv: with open('./course/course.csv') as user_csv:
@ -82,7 +76,7 @@ if __name__ == '__main__':
last_pivot = PivotVertex.objects.filter(map_course=map_obj).last() last_pivot = PivotVertex.objects.filter(map_course=map_obj).last()
if model_type == 'tutorial': if model_type == 'tutorial':
topic = Topic.objects.get(id=topic_id) topic = Topic.objects.get(id=topic_id)
small_vertex = Vertex.objects.create( small_vertex = Lesson.objects.create(
id=pk, id=pk,
video=row.pop('video', None), video=row.pop('video', None),
materials=materials, materials=materials,
@ -100,7 +94,7 @@ if __name__ == '__main__':
if model_type == 'task': if model_type == 'task':
topic = Topic.objects.get(id=topic_id) topic = Topic.objects.get(id=topic_id)
small_vertex = Vertex.objects.create( small_vertex = Lesson.objects.create(
id=pk, id=pk,
materials=materials, materials=materials,
topic=topic, topic=topic,

@ -6,20 +6,20 @@ sys.path.append("../")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup() django.setup()
from achievements.models import Diploma, Achievements from achievements.models import Diploma, Achievement
if __name__ == '__main__': if __name__ == '__main__':
Diploma.objects.all().delete() Diploma.objects.all().delete()
Achievements.objects.all().delete() Achievement.objects.all().delete()
with open('./achievement/achievement.csv') as achievements_csv: with open('./achievement/achievement.csv') as achievements_csv:
achievements_reader = csv.DictReader(achievements_csv) achievements_reader = csv.DictReader(achievements_csv)
for row in achievements_reader: for row in achievements_reader:
Achievements.objects.create(**row) Achievement.objects.create(**row)
with open('./achievement/user_achievement.csv') as achievements_csv: with open('./achievement/user_achievement.csv') as achievements_csv:
achievements_reader = csv.DictReader(achievements_csv) achievements_reader = csv.DictReader(achievements_csv)
for row in achievements_reader: for row in achievements_reader:
a = Achievements.objects.get(id=row['id']) a = Achievement.objects.get(id=row['id'])
a.users.add(get_user_model().objects.get(id=row['student_id'])) a.users.add(get_user_model().objects.get(id=row['student_id']))
with open('./achievement/diploma.csv') as achievements_csv: with open('./achievement/diploma.csv') as achievements_csv:

@ -12,8 +12,8 @@ django.setup()
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from access.models.other import Progress, PivotProgressVertex from access.models.other import Progress, ProgressLesson
from course_service.courses.models import Vertex, Course from course_service.courses.models import Lesson, Course
from course_service.maps.api import OutApiRoute from course_service.maps.api import OutApiRoute
if __name__ == '__main__': if __name__ == '__main__':
@ -48,11 +48,11 @@ if __name__ == '__main__':
pivots = json.loads(row['success']) pivots = json.loads(row['success'])
for pivot in pivots: for pivot in pivots:
try: try:
pv = PivotProgressVertex.objects.create( pv = ProgressLesson.objects.create(
progress=p, progress=p,
vertex=Vertex.objects.get(id=pivot['id']).token, vertex=Lesson.objects.get(id=pivot['id']).token,
teacher=get_user_model().objects.get(id=pivot['teacher']), teacher=get_user_model().objects.get(id=pivot['teacher']),
status=1, status='wait',
) )
if pivot['date'] and not pivot['date'] == 'None': if pivot['date'] and not pivot['date'] == 'None':
@ -60,7 +60,7 @@ if __name__ == '__main__':
pv.status = 2 pv.status = 2
pv.save() pv.save()
except Vertex.DoesNotExist: except Lesson.DoesNotExist:
pass pass
g = Group.objects.get(name='students') g = Group.objects.get(name='students')

@ -8,6 +8,7 @@ from django.contrib.auth import get_user_model
from access.models.other import Account from access.models.other import Account
if __name__ == '__main__': if __name__ == '__main__':
get_user_model().objects.all().delete()
with open('./access/users.csv') as user_csv: with open('./access/users.csv') as user_csv:
user_reader = csv.DictReader(user_csv) user_reader = csv.DictReader(user_csv)
for row in user_reader: for row in user_reader:
@ -18,6 +19,8 @@ if __name__ == '__main__':
except IndexError: except IndexError:
row['role_list'] = [] row['role_list'] = []
row.pop('id')
get_user_model().objects.get_or_create(**row) get_user_model().objects.get_or_create(**row)
except ValueError as e: except ValueError as e:
if str(e) == 'The given email must be set': if str(e) == 'The given email must be set':
@ -30,7 +33,7 @@ if __name__ == '__main__':
for row in account_reader: for row in account_reader:
row = dict(row) row = dict(row)
try: try:
acc = Account.objects.get(owner=get_user_model().objects.get(id=row['owner'])) acc = Account.objects.get(owner=get_user_model().objects.get(email=row['owner']))
acc.phone = row['phone'] if row['phone'] and len(row['phone']) < 16 else None acc.phone = row['phone'] if row['phone'] and len(row['phone']) < 16 else None
acc.city = row['city'] if row['city'] else None acc.city = row['city'] if row['city'] else None
acc.photo = row['photo'] acc.photo = row['photo']

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03 # Generated by Django 1.11.6 on 2018-01-11 10:47
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -12,8 +12,8 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('yandex_money', '0002_auto_20171128_1150'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('yandex_money', '0001_initial'),
] ]
operations = [ operations = [
@ -37,7 +37,7 @@ class Migration(migrations.Migration):
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('status', models.CharField(choices=[('W', 'Ожидание согласия'), ('P', 'На оплате'), ('F', 'Оплачен'), ('C', 'Отклонен')], default='W', max_length=1, verbose_name='Статус')), ('status', models.CharField(choices=[('W', 'Ожидание согласия'), ('P', 'На оплате'), ('F', 'Оплачен'), ('C', 'Отклонен')], default='W', max_length=1, verbose_name='Статус')),
('price', models.IntegerField(editable=False, verbose_name='Сумма')), ('price', models.IntegerField(blank=True, editable=False, null=True, verbose_name='Сумма')),
('real_price', models.IntegerField(blank=True, editable=False, help_text='Сумма, минус комиссия', null=True, verbose_name='Полученная сумма')), ('real_price', models.IntegerField(blank=True, editable=False, help_text='Сумма, минус комиссия', null=True, verbose_name='Полученная сумма')),
('method', models.CharField(choices=[('C', 'Наличные'), ('H', 'JustClick'), ('A', 'Альфа-Банк'), ('S', 'SimplePay'), ('Y', 'YandexKassa')], default='Y', max_length=2, verbose_name='Способ оплаты')), ('method', models.CharField(choices=[('C', 'Наличные'), ('H', 'JustClick'), ('A', 'Альфа-Банк'), ('S', 'SimplePay'), ('Y', 'YandexKassa')], default='Y', max_length=2, verbose_name='Способ оплаты')),
('key', models.CharField(blank=True, editable=False, max_length=255, unique=True, verbose_name='Ключ платежа')), ('key', models.CharField(blank=True, editable=False, max_length=255, unique=True, verbose_name='Ключ платежа')),

@ -1,20 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-25 11:42
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('finance', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='invoice',
name='price',
field=models.IntegerField(blank=True, editable=False, null=True, verbose_name='Сумма'),
),
]

@ -3,7 +3,7 @@ from django.conf import settings
from django.db import models from django.db import models
from yandex_money.models import Payment from yandex_money.models import Payment
from course_service.courses.models import Course, Vertex from courses.models import Course, Lesson
class Bill(models.Model): class Bill(models.Model):

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03 # Generated by Django 1.11.6 on 2018-01-11 10:47
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime

@ -107,8 +107,7 @@ libs = (
apps = ( apps = (
'access', 'access',
'course_service.maps', 'courses',
'course_service.courses',
'storage', 'storage',
'finance', 'finance',
'library', 'library',

@ -1,3 +1,4 @@
django-model-utils
celery==4.1.0 celery==4.1.0
Django==1.11.6 Django==1.11.6
django-celery-beat==1.0.1 django-celery-beat==1.0.1

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-17 18:03 # Generated by Django 1.11.6 on 2018-01-11 10:47
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models

Loading…
Cancel
Save