parent
693895a90a
commit
e97c343995
41 changed files with 100 additions and 972 deletions
@ -1,61 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
|
||||||
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): |
|
||||||
|
|
||||||
initial = True |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('access', '0001_initial'), |
|
||||||
('auth', '0008_alter_user_username_max_length'), |
|
||||||
('maps', '0001_initial'), |
|
||||||
('courses', '0002_auto_20171128_1518'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='course', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='progress_list', |
|
||||||
field=models.ManyToManyField(blank=True, to='courses.Vertex', verbose_name='Лист пройденных объектов'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='template', |
|
||||||
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='Шаблон для прохождения если не указан явно смотри функцию get_template()'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='progress', |
|
||||||
name='user', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='account', |
|
||||||
name='owner', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='user', |
|
||||||
name='groups', |
|
||||||
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='user', |
|
||||||
name='user_permissions', |
|
||||||
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'), |
|
||||||
), |
|
||||||
migrations.AlterUniqueTogether( |
|
||||||
name='progress', |
|
||||||
unique_together=set([('user', 'course')]), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,27 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-29 16:39 |
|
||||||
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_20171128_1518'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterField( |
|
||||||
model_name='progress', |
|
||||||
name='course', |
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='progress', |
|
||||||
name='user', |
|
||||||
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,46 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-11 14:18 |
|
||||||
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', '0003_auto_20171129_1639'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.CreateModel( |
|
||||||
name='Invite', |
|
||||||
fields=[ |
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
||||||
('hash', models.CharField(max_length=15, unique=True, verbose_name='Уникальный код')), |
|
||||||
('date', models.DateTimeField(blank=True, null=True, verbose_name='Дата сгорания приглошения')), |
|
||||||
], |
|
||||||
options={ |
|
||||||
'verbose_name': 'Приглошение в систему', |
|
||||||
'verbose_name_plural': 'Приглошения в систему', |
|
||||||
}, |
|
||||||
), |
|
||||||
migrations.CreateModel( |
|
||||||
name='ResetPassword', |
|
||||||
fields=[ |
|
||||||
('invite_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='access.Invite')), |
|
||||||
('password', models.CharField(max_length=63, verbose_name='Новый пароль, если есть')), |
|
||||||
], |
|
||||||
options={ |
|
||||||
'verbose_name': 'Запрос на сброс пароля', |
|
||||||
'verbose_name_plural': 'Запросы на сброс пароля', |
|
||||||
}, |
|
||||||
bases=('access.invite',), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='invite', |
|
||||||
name='owner', |
|
||||||
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Кому приглошение'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,56 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
|
||||||
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): |
|
||||||
|
|
||||||
initial = True |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('achievements', '0001_initial'), |
|
||||||
('courses', '0001_initial'), |
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='skillj', |
|
||||||
name='lesson', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='Урок'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='skillj', |
|
||||||
name='skill', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='achievements.Skills', verbose_name='Навык'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='diplomagen', |
|
||||||
name='course', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'), |
|
||||||
), |
|
||||||
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), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='achievements', |
|
||||||
name='course', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='achievements', |
|
||||||
name='user', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,24 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-05 18:21 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('achievements', '0002_auto_20171128_1518'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.RemoveField( |
|
||||||
model_name='achievements', |
|
||||||
name='course', |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='achievements', |
|
||||||
name='icon', |
|
||||||
field=models.ImageField(blank=True, null=True, upload_to='achives', verbose_name='Отображение достижения'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,26 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-05 18:23 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.conf import settings |
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
|
||||||
('achievements', '0003_auto_20171205_1821'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.RemoveField( |
|
||||||
model_name='achievements', |
|
||||||
name='user', |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='achievements', |
|
||||||
name='user', |
|
||||||
field=models.ManyToManyField(to=settings.AUTH_USER_MODEL), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,25 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-05 18:33 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('achievements', '0004_auto_20171205_1823'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.RenameField( |
|
||||||
model_name='achievements', |
|
||||||
old_name='icon', |
|
||||||
new_name='img', |
|
||||||
), |
|
||||||
migrations.RenameField( |
|
||||||
model_name='diploma', |
|
||||||
old_name='icon', |
|
||||||
new_name='img', |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-05 18:36 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('achievements', '0005_auto_20171205_1833'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.RenameField( |
|
||||||
model_name='achievements', |
|
||||||
old_name='user', |
|
||||||
new_name='users', |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-06 12:44 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('achievements', '0006_auto_20171205_1836'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='achievements', |
|
||||||
name='text', |
|
||||||
field=models.CharField(default='', max_length=255, verbose_name='Текст достижения'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,31 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
|
||||||
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): |
|
||||||
|
|
||||||
initial = True |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('courses', '0001_initial'), |
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
|
||||||
('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='Порядок прохождения по умолчанию'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='course', |
|
||||||
name='teachers', |
|
||||||
field=models.ManyToManyField(related_name='course_teachers', to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,19 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-05 11:23 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('courses', '0002_auto_20171128_1518'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.RemoveField( |
|
||||||
model_name='course', |
|
||||||
name='mentors', |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1 +0,0 @@ |
|||||||
default_app_config = "journals.apps.JournalsAppConfig" |
|
||||||
@ -1,5 +0,0 @@ |
|||||||
from django.contrib import admin |
|
||||||
from journals.models import Thread, Journal |
|
||||||
|
|
||||||
admin.site.register(Thread) |
|
||||||
admin.site.register(Journal) |
|
||||||
@ -1,7 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
from django.apps import AppConfig |
|
||||||
|
|
||||||
|
|
||||||
class JournalsAppConfig(AppConfig): |
|
||||||
name = "journals" |
|
||||||
verbose_name = "Журналы" |
|
||||||
@ -1,75 +0,0 @@ |
|||||||
import os, sys, django |
|
||||||
|
|
||||||
from django.contrib.auth import get_user_model |
|
||||||
|
|
||||||
sys.path.append("../") |
|
||||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings") |
|
||||||
django.setup() |
|
||||||
|
|
||||||
|
|
||||||
from journals.models import Thread |
|
||||||
from django.contrib.auth.models import Group |
|
||||||
from lms.global_decorators import transaction_decorator |
|
||||||
|
|
||||||
|
|
||||||
@transaction_decorator |
|
||||||
def main_threads(): |
|
||||||
Thread.objects.all().delete() |
|
||||||
|
|
||||||
admin_thread = Thread.objects.create( |
|
||||||
key='Admin', |
|
||||||
text='Тред для админов, сюда падают все журналируемые сообщения в системе, кроме личных переписок', |
|
||||||
is_staff=True, |
|
||||||
x=500, |
|
||||||
y=75, |
|
||||||
) |
|
||||||
|
|
||||||
admin_thread.groups.add(Group.objects.get(name='admin')) |
|
||||||
|
|
||||||
management_thread = Thread.objects.create( |
|
||||||
key='Project_management', |
|
||||||
text='Тред для проджект-менеджеров, сюда падает статистика разного рода', |
|
||||||
is_staff=True, |
|
||||||
) |
|
||||||
|
|
||||||
management_thread.groups.add(Group.objects.get(name='project_managers')) |
|
||||||
management_thread.parent.add(admin_thread) |
|
||||||
|
|
||||||
support_thread = Thread.objects.create( |
|
||||||
key='Support', |
|
||||||
text='Тред сапортов, занимаются поддержкой клиента', |
|
||||||
is_staff=True, |
|
||||||
y=500, |
|
||||||
) |
|
||||||
|
|
||||||
support_thread.groups.add(Group.objects.get(name='supports')) |
|
||||||
support_thread.parent.add(management_thread) |
|
||||||
|
|
||||||
lead_managers = Thread.objects.create( |
|
||||||
key='Sale_lead', |
|
||||||
text='Тред лидов, сейлзов', |
|
||||||
is_staff=True, |
|
||||||
x=700, |
|
||||||
) |
|
||||||
|
|
||||||
lead_managers.groups.add(Group.objects.get(name='lead_managers')) |
|
||||||
lead_managers.parent.add(admin_thread) |
|
||||||
|
|
||||||
managers = Thread.objects.create( |
|
||||||
key='Sale', |
|
||||||
text='Тред сейлзов', |
|
||||||
is_staff=True, |
|
||||||
is_recurse=True, |
|
||||||
x=700, |
|
||||||
y=500, |
|
||||||
) |
|
||||||
|
|
||||||
managers.groups.add(Group.objects.get(name='managers')) |
|
||||||
managers.parent.add(lead_managers) |
|
||||||
|
|
||||||
for user in get_user_model().objects.all(): |
|
||||||
Thread.objects.get_or_create(key="""user_%s""" % user.id) |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
main_threads() |
|
||||||
@ -1,60 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-28 15:18 |
|
||||||
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): |
|
||||||
|
|
||||||
initial = True |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('storage', '0001_initial'), |
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL), |
|
||||||
('auth', '0008_alter_user_username_max_length'), |
|
||||||
('contenttypes', '0002_remove_content_type_name'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.CreateModel( |
|
||||||
name='Journal', |
|
||||||
fields=[ |
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
||||||
('extra_data', models.TextField(blank=True, null=True)), |
|
||||||
('object_id', models.PositiveIntegerField()), |
|
||||||
('action_type', models.CharField(choices=[('try', 'попытался сдать'), ('yes', 'одобрил'), ('no', 'отклонил'), ('favorite', 'добавил в избранное'), ('watch', 'просмотрел'), ('like', 'лайкнул'), ('dislike', 'дизлайкнул'), ('comment', 'оставил комментарий'), ('start', 'начал прохождение'), ('end', 'закончил прохождение'), ('create', 'создал'), ('update', 'обновил'), ('delete', 'удалил')], max_length=31)), |
|
||||||
('date', models.DateTimeField(auto_now_add=True)), |
|
||||||
('content_type', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='contenttypes.ContentType')), |
|
||||||
('files', models.ManyToManyField(blank=True, to='storage.Storage')), |
|
||||||
], |
|
||||||
), |
|
||||||
migrations.CreateModel( |
|
||||||
name='Thread', |
|
||||||
fields=[ |
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
||||||
('key', models.CharField(editable=False, max_length=200, unique=True)), |
|
||||||
('text', models.TextField(default='', verbose_name='Описание треда')), |
|
||||||
('is_staff', models.BooleanField(default=False, verbose_name='Админская ли табличка')), |
|
||||||
('is_recurse', models.BooleanField(default=False, verbose_name='Поле аптимизации поиска')), |
|
||||||
('check_subscribe', models.BooleanField(default=True, verbose_name='Проверять ли подписки')), |
|
||||||
('x', models.SmallIntegerField(default=300)), |
|
||||||
('y', models.SmallIntegerField(default=300)), |
|
||||||
('groups', models.ManyToManyField(blank=True, to='auth.Group', verbose_name='Группы подписчиков')), |
|
||||||
('parent', models.ManyToManyField(blank=True, to='journals.Thread')), |
|
||||||
('subscribers', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL, verbose_name='Подписчики')), |
|
||||||
], |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='journal', |
|
||||||
name='thread', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='journals.Thread', verbose_name='Тред'), |
|
||||||
), |
|
||||||
migrations.AddField( |
|
||||||
model_name='journal', |
|
||||||
name='user', |
|
||||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Инициатор действия или тот, на ком действие инициируется'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,100 +0,0 @@ |
|||||||
# coding=utf-8 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.conf import settings |
|
||||||
from django.contrib.auth.models import Group |
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey |
|
||||||
from django.contrib.contenttypes.models import ContentType |
|
||||||
from django.db import models |
|
||||||
from django.db import connection |
|
||||||
|
|
||||||
from courses.models import Course |
|
||||||
from finance.models import Bill |
|
||||||
from storage.models import Storage |
|
||||||
|
|
||||||
ACTION_CHOICES = ( |
|
||||||
('try', 'попытался сдать'), |
|
||||||
('yes', 'одобрил'), |
|
||||||
('no', 'отклонил'), |
|
||||||
('favorite', 'добавил в избранное'), |
|
||||||
('watch', 'просмотрел'), |
|
||||||
('like', 'лайкнул'), |
|
||||||
('dislike', 'дизлайкнул'), |
|
||||||
('comment', 'оставил комментарий'), |
|
||||||
('start', 'начал прохождение'), |
|
||||||
('end', 'закончил прохождение'), |
|
||||||
('create', 'создал'), |
|
||||||
('update', 'обновил'), |
|
||||||
('delete', 'удалил'), |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
class Journal(models.Model): |
|
||||||
thread = models.ForeignKey(to='Thread', verbose_name='Тред') |
|
||||||
user = models.ForeignKey( |
|
||||||
to=settings.AUTH_USER_MODEL, verbose_name='Инициатор действия или тот, на ком действие инициируется' |
|
||||||
) |
|
||||||
content_type = models.ForeignKey(to=ContentType) |
|
||||||
extra_data = models.TextField(null=True, blank=True) |
|
||||||
object_id = models.PositiveIntegerField() |
|
||||||
content_object = GenericForeignKey('content_type', 'object_id') |
|
||||||
action_type = models.CharField(max_length=31, choices=ACTION_CHOICES) |
|
||||||
date = models.DateTimeField(auto_now_add=True) |
|
||||||
files = models.ManyToManyField(to=Storage, blank=True) |
|
||||||
|
|
||||||
def __str__(self): |
|
||||||
return '%d Пользователь %s %s %s' % (self.id, self.user.email, self.get_action_type_display(), self.thread.key) |
|
||||||
|
|
||||||
|
|
||||||
class Thread(models.Model): |
|
||||||
key = models.CharField(max_length=200, unique=True, editable=False) |
|
||||||
text = models.TextField(default='', verbose_name='Описание треда') |
|
||||||
is_staff = models.BooleanField(default=False, verbose_name='Админская ли табличка') |
|
||||||
is_recurse = models.BooleanField(default=False, verbose_name='Поле аптимизации поиска') |
|
||||||
subscribers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Подписчики', blank=True) |
|
||||||
groups = models.ManyToManyField(to=Group, verbose_name='Группы подписчиков', blank=True) |
|
||||||
check_subscribe = models.BooleanField(default=True, verbose_name='Проверять ли подписки') |
|
||||||
parent = models.ManyToManyField(to='self', blank=True, symmetrical=False) |
|
||||||
x = models.SmallIntegerField(default=300) |
|
||||||
y = models.SmallIntegerField(default=300) |
|
||||||
|
|
||||||
def check_status(self): |
|
||||||
# Определяет статус треда если такой есть. |
|
||||||
# Возможно, костыль. |
|
||||||
res = None |
|
||||||
for i in self.journal_set.all(): |
|
||||||
if i.action_type in ['try', 'yes', 'no']: |
|
||||||
res = i.action_type |
|
||||||
return res |
|
||||||
|
|
||||||
def check_perm(self, user): |
|
||||||
res = user in self.subscribers.all() |
|
||||||
for i in self.groups.all(): |
|
||||||
res = res or (i in user.groups.all()) |
|
||||||
return res or sum([int(i.check_perm(user)) for i in self.parent.all()]) |
|
||||||
|
|
||||||
def child_thread_count(self): |
|
||||||
# cursor = connection.cursor() |
|
||||||
# if self.is_recurse: |
|
||||||
# cursor.execute(""" |
|
||||||
# WITH RECURSIVE temp1 (to_thread_id, from_thread_id) AS ( |
|
||||||
# SELECT T1.to_thread_id, T1.from_thread_id |
|
||||||
# FROM journals_thread_parent T1 |
|
||||||
# WHERE to_thread_id = %s |
|
||||||
# UNION |
|
||||||
# SELECT T2.to_thread_id, T2.from_thread_id |
|
||||||
# FROM journals_thread_parent T2 |
|
||||||
# INNER JOIN temp1 ON(T2.from_thread_id = temp1.to_thread_id) |
|
||||||
# ) |
|
||||||
# SELECT COUNT(*) FROM temp1 |
|
||||||
# """, [self.id]) |
|
||||||
# count = cursor.fetchone() |
|
||||||
# return int(count[0]) |
|
||||||
|
|
||||||
return self.thread_set.count() |
|
||||||
|
|
||||||
def journals_count(self): |
|
||||||
return self.journal_set.count() |
|
||||||
|
|
||||||
def __str__(self): |
|
||||||
return self.key |
|
||||||
@ -1,68 +0,0 @@ |
|||||||
from rest_framework import serializers |
|
||||||
|
|
||||||
from journals.models import Thread, Journal |
|
||||||
from storage.serializers import StorageSerializer |
|
||||||
|
|
||||||
|
|
||||||
class JournalSerializer(serializers.ModelSerializer): |
|
||||||
user = serializers.SerializerMethodField() |
|
||||||
files = serializers.SerializerMethodField() |
|
||||||
label = serializers.SerializerMethodField() |
|
||||||
|
|
||||||
class Meta: |
|
||||||
model = Journal |
|
||||||
fields = ('label', 'date', 'user', 'files', 'action_type', 'object_id', ) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_user(self): |
|
||||||
return self.user.get_full_name() |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_label(self): |
|
||||||
return self.extra_data if self.extra_data else """%s %s"""\ |
|
||||||
% (self.user.get_full_name(), self.get_action_type_display()) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_files(self): |
|
||||||
return [StorageSerializer(i).data for i in self.files.all()] |
|
||||||
|
|
||||||
|
|
||||||
class ThreadDetailSerializer(serializers.ModelSerializer): |
|
||||||
journals = serializers.SerializerMethodField() |
|
||||||
children = serializers.SerializerMethodField() |
|
||||||
|
|
||||||
class Meta: |
|
||||||
model = Thread |
|
||||||
fields = ('journals', 'id', 'text', 'children', 'key',) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_journals(self): |
|
||||||
return [JournalSerializer(i).data for i in self.journal_set.all()] |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_children(self): |
|
||||||
return [ThreadDetailSerializer(i).data for i in self.thread_set.all()] |
|
||||||
|
|
||||||
|
|
||||||
class ThreadAdminSerializer(serializers.ModelSerializer): |
|
||||||
count_children = serializers.SerializerMethodField() |
|
||||||
count_journals = serializers.SerializerMethodField() |
|
||||||
|
|
||||||
class Meta: |
|
||||||
model = Thread |
|
||||||
exclude = ('is_staff', ) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_count_children(self): |
|
||||||
return self.child_thread_count() |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get_count_journals(self): |
|
||||||
return self.journals_count() |
|
||||||
|
|
||||||
|
|
||||||
class ThreadUserSerializer(serializers.ModelSerializer): |
|
||||||
|
|
||||||
class Meta: |
|
||||||
model = Thread |
|
||||||
fields = ('id', 'text') |
|
||||||
@ -1,9 +0,0 @@ |
|||||||
from django.conf.urls import url |
|
||||||
from journals import views as views |
|
||||||
|
|
||||||
urlpatterns = [ |
|
||||||
url(r'thread/$', views.ThreadAdminListView.as_view()), |
|
||||||
url(r'pay-stat/([0-9]{1,99})/$', views.get_pay_stat), |
|
||||||
url(r'thread/(?P<key>[-\w]+)/$', views.ThreadDetailView.as_view()), |
|
||||||
url(r'journal/$', views.JournalCreateView.as_view()), |
|
||||||
] |
|
||||||
@ -1,131 +0,0 @@ |
|||||||
from django.contrib.auth import get_user_model |
|
||||||
from django.contrib.contenttypes.models import ContentType |
|
||||||
from rest_framework.permissions import IsAuthenticated |
|
||||||
from rest_framework.views import APIView |
|
||||||
from rest_framework.renderers import JSONRenderer |
|
||||||
from rest_framework.response import Response |
|
||||||
import csv |
|
||||||
from django.http import HttpResponse, HttpResponseForbidden |
|
||||||
|
|
||||||
from access.models.other import Progress |
|
||||||
from journals.models import Thread, Journal |
|
||||||
from journals.serilizers import ThreadDetailSerializer, ThreadAdminSerializer, JournalSerializer |
|
||||||
from lms.global_decorators import transaction_decorator |
|
||||||
from lms.tools import decode_base64 |
|
||||||
from storage.models import Storage |
|
||||||
|
|
||||||
|
|
||||||
class ThreadAdminListView(APIView): |
|
||||||
renderer_classes = (JSONRenderer,) |
|
||||||
status_code = 200 |
|
||||||
|
|
||||||
def get(self, request): |
|
||||||
return Response( |
|
||||||
[ThreadAdminSerializer(thread).data for thread in Thread.objects.filter(is_staff=True)], |
|
||||||
self.status_code, |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
class ThreadDetailView(APIView): |
|
||||||
renderer_classes = (JSONRenderer,) |
|
||||||
permission_classes = () |
|
||||||
status_code = 200 |
|
||||||
|
|
||||||
def post(self, request, key): |
|
||||||
try: |
|
||||||
thread = Thread.objects.get(key=key) |
|
||||||
thread.text = request.JSON.get('text', thread.text) |
|
||||||
thread.key = request.JSON.get('key', thread.key) |
|
||||||
thread.x = request.JSON.get('x', thread.x) |
|
||||||
thread.y = request.JSON.get('y', thread.y) |
|
||||||
thread.save() |
|
||||||
return Response(ThreadAdminSerializer(thread).data, self.status_code, ) |
|
||||||
except Thread.DoesNotExist: |
|
||||||
return Response("Thread doesn't exist.", self.status_code, ) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def get(request, key): |
|
||||||
try: |
|
||||||
thread = Thread.objects.get(key=key) |
|
||||||
if thread.check_perm(request.user): |
|
||||||
return Response(ThreadDetailSerializer(thread).data, status=200) |
|
||||||
return Response("permission denied", status=403) |
|
||||||
|
|
||||||
except Thread.DoesNotExist: |
|
||||||
return Response("Thread not found", status=404) |
|
||||||
|
|
||||||
|
|
||||||
def get_pay_stat(request, pk): |
|
||||||
if not request.user.is_authenticated and (request.user.groups.filter(name="supports") or request.user.is_superuser): |
|
||||||
return HttpResponseForbidden() |
|
||||||
|
|
||||||
date_from = request.GET.get('from', None) |
|
||||||
date_to = request.GET.get('to', None) |
|
||||||
|
|
||||||
file_name = "teacher_%s" % pk |
|
||||||
file_name = file_name + "__from_%s" % date_from if date_from else file_name |
|
||||||
file_name = file_name + "__to_%s" % date_to if date_to else file_name |
|
||||||
|
|
||||||
journals = Journal.objects.filter(user_id=pk, action_type="yes") |
|
||||||
journals = journals.filter(date__lt=date_to) if date_to else journals |
|
||||||
journals = journals.filter(date__gte=date_from) if date_from else journals |
|
||||||
|
|
||||||
response = HttpResponse(content_type='text/csv') |
|
||||||
response['Content-Disposition'] = 'attachment; filename="%s"' % file_name |
|
||||||
|
|
||||||
writer = csv.writer(response) |
|
||||||
writer.writerow(['student_email', 'full_name', 'course', 'theme', 'task_id', 'date']) |
|
||||||
|
|
||||||
for i in journals.order_by('-date'): |
|
||||||
student = get_user_model().objects.get(id=i.thread.key.split('user_')[1].split('__vertex')[0]) |
|
||||||
writer.writerow([ |
|
||||||
student.email, |
|
||||||
student.get_full_name(), |
|
||||||
i.content_object.course.title, |
|
||||||
i.content_object.vertex_set.all()[0].title, |
|
||||||
i.content_object.id, |
|
||||||
i.date, |
|
||||||
]) |
|
||||||
|
|
||||||
return response |
|
||||||
|
|
||||||
|
|
||||||
class JournalCreateView(APIView): |
|
||||||
renderer_classes = (JSONRenderer,) |
|
||||||
permission_classes = (IsAuthenticated,) |
|
||||||
status_code = 200 |
|
||||||
|
|
||||||
@transaction_decorator |
|
||||||
def post(self, request): |
|
||||||
pk = request.JSON.get('thread_id', None) |
|
||||||
try: |
|
||||||
thread = Thread.objects.get(id=pk) |
|
||||||
if request.user.is_authenticated and thread.check_perm(request.user): |
|
||||||
action_type = request.JSON.get('action_type', None) |
|
||||||
extra_data = request.JSON.get('extra_data', None) |
|
||||||
object_id = request.JSON.get('object_id', None) |
|
||||||
content_type__model = request.JSON.get('content_type__model', None) |
|
||||||
content_type__app_label = request.JSON.get('content_type__app_label', None) |
|
||||||
content_type = ContentType.objects.get(model=content_type__model, app_label=content_type__app_label) |
|
||||||
|
|
||||||
files = request.JSON.get('files', []) |
|
||||||
files = [{'data': decode_base64(i['data']), 'name': i['name']} for i in files] |
|
||||||
|
|
||||||
journal = Journal.objects.create( |
|
||||||
action_type=action_type, extra_data=extra_data, thread=thread, |
|
||||||
content_type=content_type, object_id=object_id, |
|
||||||
user=request.user |
|
||||||
) |
|
||||||
|
|
||||||
for i in files: |
|
||||||
s = Storage.objects.create(original=decode_base64(i['data']), name=i['name']) |
|
||||||
journal.files.add(s) |
|
||||||
|
|
||||||
if action_type == 'yes': |
|
||||||
p = Progress.objects.get(course=journal.content_object.course, user=journal.thread.subscribers.all()[0]) |
|
||||||
p.add_vertex(journal.content_object) |
|
||||||
|
|
||||||
return Response(JournalSerializer(journal).data, status=200) |
|
||||||
return Response("permission denied", status=403) |
|
||||||
except Thread.DoesNotExist: |
|
||||||
return Response("Thread doesn't exist.", self.status_code,) |
|
||||||
@ -1,24 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-29 14:39 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('courses', '0002_auto_20171128_1518'), |
|
||||||
('maps', '0001_initial'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterUniqueTogether( |
|
||||||
name='pivotcoursemap', |
|
||||||
unique_together=set([('map_course', 'route'), ('sort', 'route')]), |
|
||||||
), |
|
||||||
migrations.AlterUniqueTogether( |
|
||||||
name='pivotvertex', |
|
||||||
unique_together=set([('sort', 'map_course'), ('map_course', 'vertex')]), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,25 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-29 14:41 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('maps', '0002_auto_20171129_1439'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterField( |
|
||||||
model_name='pivotcoursemap', |
|
||||||
name='sort', |
|
||||||
field=models.SmallIntegerField(verbose_name='Порядок сортировки'), |
|
||||||
), |
|
||||||
migrations.AlterField( |
|
||||||
model_name='pivotvertex', |
|
||||||
name='sort', |
|
||||||
field=models.SmallIntegerField(verbose_name='Порядок сортировки'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,19 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-11-29 14:47 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('maps', '0003_auto_20171129_1441'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterModelOptions( |
|
||||||
name='pivotcoursemap', |
|
||||||
options={'ordering': ('sort',), 'verbose_name': 'Порядок сортировки маршрута', 'verbose_name_plural': 'Порядки сортировок маршрутов'}, |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-01 20:12 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('maps', '0004_auto_20171129_1447'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AddField( |
|
||||||
model_name='coursemap', |
|
||||||
name='name', |
|
||||||
field=models.CharField(default='Линейное прохождение', max_length=255, verbose_name='Имя прохождения'), |
|
||||||
), |
|
||||||
] |
|
||||||
@ -1,20 +0,0 @@ |
|||||||
# -*- coding: utf-8 -*- |
|
||||||
# Generated by Django 1.11.6 on 2017-12-06 12:58 |
|
||||||
from __future__ import unicode_literals |
|
||||||
|
|
||||||
from django.db import migrations, models |
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration): |
|
||||||
|
|
||||||
dependencies = [ |
|
||||||
('maps', '0005_coursemap_name'), |
|
||||||
] |
|
||||||
|
|
||||||
operations = [ |
|
||||||
migrations.AlterField( |
|
||||||
model_name='courseroute', |
|
||||||
name='name', |
|
||||||
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='Имя шаблона'), |
|
||||||
), |
|
||||||
] |
|
||||||
Loading…
Reference in new issue