From 514671b31f9d4326dc649043171dbcb232708cf2 Mon Sep 17 00:00:00 2001 From: Andrey Date: Fri, 17 Nov 2017 13:32:23 +0300 Subject: [PATCH] a --- access/management/__init__.py | 0 .../commands/add_users_in_groups.py | 45 +++++++++++++++ access/migrations/0008_auto_20171117_1113.py | 20 +++++++ access/models.py | 7 ++- access/serializers.py | 57 ++++++++++++++++++- access/views.py | 4 +- courses/models.py | 39 ++++++++++--- finance/urls.py | 2 +- finance/views.py | 18 +++--- 9 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 access/management/__init__.py create mode 100644 access/management/commands/add_users_in_groups.py create mode 100644 access/migrations/0008_auto_20171117_1113.py diff --git a/access/management/__init__.py b/access/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/access/management/commands/add_users_in_groups.py b/access/management/commands/add_users_in_groups.py new file mode 100644 index 0000000..5d8b87f --- /dev/null +++ b/access/management/commands/add_users_in_groups.py @@ -0,0 +1,45 @@ +from django.contrib.auth import get_user_model +from django.contrib.auth.models import Group +from django.core.management.base import BaseCommand, CommandError +import os +import shutil +from django.conf import settings + + +class Command(BaseCommand): + help = 'Добавляет 1 или нескольких юзеров в указанные группы' + + def add_arguments(self, parser): + parser.add_argument( + '--users', + type=str, + dest='users_emails', + help='Емейлы пользователей для добавления' + ) + parser.add_argument( + '--groups', + type=str, + dest='groups_names', + help='Наименования групп для добавления' + ) + + def handle(self, *args, **options): + for email in options['users_emails'].split(', '): + try: + user = get_user_model().objects.get(email=email) + + for name in options['groups_names'].split(', '): + try: + g = Group.objects.get(name=name) + except Group.DoesNotExist: + print("""Group with name "%s" doesn't exist""") + + if name == "admin": + user.is_superuser = True + user.is_staff = True + if name != "students": + user.is_staff = True + g.user_set.add(user) + user.save() + except get_user_model().DoesNotExist: + print("""user with email: "%s" not found""" % email) \ No newline at end of file diff --git a/access/migrations/0008_auto_20171117_1113.py b/access/migrations/0008_auto_20171117_1113.py new file mode 100644 index 0000000..62ba563 --- /dev/null +++ b/access/migrations/0008_auto_20171117_1113.py @@ -0,0 +1,20 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.11.6 on 2017-11-17 11:13 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('courses', '0007_auto_20171103_1627'), + ('access', '0007_auto_20171106_1808'), + ] + + operations = [ + migrations.AlterUniqueTogether( + name='progress', + unique_together=set([('user', 'course')]), + ), + ] diff --git a/access/models.py b/access/models.py index 46aff9e..c4240c0 100755 --- a/access/models.py +++ b/access/models.py @@ -181,12 +181,13 @@ class Progress(models.Model): class Meta: verbose_name = 'Прогресс пользователя' verbose_name_plural = 'Прогресс пользователя' + unique_together = ("user", "course") class ExtraPrivilege(models.Model): - user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name=u'Правообладатель') - is_done = models.BooleanField(default=False, verbose_name=u'Выполнено?') - subject = models.ForeignKey(to=Vertex, verbose_name=u'Объект') + user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Правообладатель') + is_done = models.BooleanField(default=False, verbose_name='Выполнено?') + subject = models.ForeignKey(to=Vertex, verbose_name='Объект') class Meta: verbose_name = 'Доп право' diff --git a/access/serializers.py b/access/serializers.py index c768798..73d531a 100644 --- a/access/serializers.py +++ b/access/serializers.py @@ -1,6 +1,36 @@ from django.contrib.auth import get_user_model from rest_framework import serializers -from access.models import ExtraPrivilege, Account +from access.models import ExtraPrivilege, Account, Progress +from courses.serializers import MiniVertexSerializer + + +class ProgressSerializer(serializers.ModelSerializer): + vertex = serializers.SerializerMethodField() + course = serializers.SerializerMethodField() + max = serializers.SerializerMethodField() + number = serializers.SerializerMethodField() + + class Meta: + model = Progress + fields = ('course', 'vertex', 'number', 'max') + + @staticmethod + def get_max(self): + return self.course.get_vertexes('topic').count() + + @staticmethod + def get_number(self): + if self.success: + return self.get_max() + return self.active_obj.get_number('topic') + + @staticmethod + def get_course(self): + return {'title': self.course.title, 'slug': self.course.slug} + + @staticmethod + def get_vertex(self): + return MiniVertexSerializer(self.active_obj).data class AccountSerializer(serializers.ModelSerializer): @@ -32,6 +62,31 @@ class UserInitSerializer(serializers.ModelSerializer): return [group.name for group in self.groups.all()] +class UserProfileSerializer(serializers.ModelSerializer): + account = serializers.SerializerMethodField() + groups = serializers.SerializerMethodField() + progress = serializers.SerializerMethodField() + + class Meta: + model = get_user_model() + fields = ( + 'id', 'email', 'first_name', 'last_name','progress', + 'account', 'groups', 'is_staff', 'is_superuser', + ) + + @staticmethod + def get_progress(self): + return [ProgressSerializer(i).data for i in self.progress_set.all()] + + @staticmethod + def get_account(self): + return AccountSerializer(self.account).data + + @staticmethod + def get_groups(self): + return [group.name for group in self.groups.all()] + + class UserSearchSerializer(serializers.ModelSerializer): pay = serializers.SerializerMethodField() phone = serializers.SerializerMethodField() diff --git a/access/views.py b/access/views.py index e90549d..cd14ef9 100644 --- a/access/views.py +++ b/access/views.py @@ -7,7 +7,7 @@ from rest_framework.response import Response from django.db.models import Q from access.models import Invite, Progress, ExtraPrivilege -from access.serializers import UserInitSerializer, UserSearchSerializer +from access.serializers import UserInitSerializer, UserSearchSerializer, UserProfileSerializer from courses.models import Vertex @@ -83,7 +83,7 @@ class DetailUserView(APIView): except get_user_model().DoesNotExist: return Response("User doesn't exist", status=404) - return Response(UserInitSerializer(user).data, status=200) + return Response(UserProfileSerializer(user).data, status=200) return Response('Permission denied', status=403) diff --git a/courses/models.py b/courses/models.py index b2f6136..1cbfe80 100755 --- a/courses/models.py +++ b/courses/models.py @@ -86,7 +86,7 @@ class Course(models.Model): image = models.URLField(verbose_name='Изображение', blank=True, max_length=255) big_image = models.URLField(verbose_name='Большое изображение', blank=True, max_length=255) big_mobile_image = models.URLField(verbose_name='Под мобилку', blank=True, null=True, - help_text='Большая картинка для мобильной версии', max_length=255) + help_text='Большая картинка для мобильной версии', max_length=255) teachers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели', related_name='course_teachers') @@ -111,17 +111,24 @@ class Course(models.Model): return helper(course_map) + def get_vertexes(self, vertex_type=None): + course_map = CourseMap.objects.get(course=self).map_to_list() + + if vertex_type: + return self.vertex_set.filter(content_type__model=vertex_type, id__in=course_map) + return course_map + def get_statistic(self): """ Минималистичная статистика по уроку, количество тем, уроков, домашек. """ - topic_count = Vertex.objects.filter(course=self, content_type__model='topic').count() - task_count = Vertex.objects.filter(course=self, content_type__model='task').count() - tutorial_count = Vertex.objects.filter(course=self, content_type__model='tutorial').count() - - return {"topic_count": topic_count, "tutorial_count": tutorial_count, "task_count": task_count} + return { + "topic_count": self.get_vertexes('topic').count(), + "tutorial_count": self.get_vertexes('task').count(), + "task_count": self.get_vertexes('tutorial').count(), + } def get_first(self, vertex_model_list=None): if vertex_model_list is None: @@ -171,8 +178,8 @@ class Skills(models.Model): def __str__(self): return '%s' % self.title class Meta: - verbose_name = u'Навык' - verbose_name_plural = u'Навыки' + verbose_name = 'Навык' + verbose_name_plural = 'Навыки' class SkillJ(models.Model): @@ -332,6 +339,22 @@ class Vertex(models.Model): return progress.is_access(self) + def get_number(self, vertex_type=None): + """ + Возврощает порядковый номер узла с определённым типом. + Пример мы хотим определит какой по счёту теме принадлежит конкретно взятый урок. + """ + vertex_list = list(self.course.get_vertexes(vertex_type)) + try: + res = vertex_list.index(self) + except ValueError: + parents = self.vertex_set.all() + if parents.count() == 1: + res = vertex_list.index(parents[0]) + else: + res = None + return res + # Модели нового API со временем всё, что выше будет выпилено class Tutorial(models.Model): diff --git a/finance/urls.py b/finance/urls.py index dcf4465..37a229d 100644 --- a/finance/urls.py +++ b/finance/urls.py @@ -5,5 +5,5 @@ urlpatterns = [ url(r'bills/([0-9]{1,99})/$', views.BillDetailView.as_view()), url(r'payment/([0-9]{1,99})/$', views.YandexPay.as_view()), url(r'bills/$', views.BillListView.as_view()), - + url(r'invoices/$', views.get_invoices), ] \ No newline at end of file diff --git a/finance/views.py b/finance/views.py index 862ea45..637bb9d 100644 --- a/finance/views.py +++ b/finance/views.py @@ -131,7 +131,7 @@ def get_invoices(request): 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 - invoices = Invoice.objects.filter() + invoices = Invoice.objects.filter(method="Y", status="F") invoices = invoices.filter(date__lt=date_to) if date_to else invoices invoices = invoices.filter(date__gte=date_from) if date_from else invoices @@ -139,17 +139,17 @@ def get_invoices(request): response['Content-Disposition'] = 'attachment; filename="%s"' % file_name writer = csv.writer(response) - writer.writerow(['student_email', 'full_name', 'course', 'theme', 'task_id', 'date']) + writer.writerow(['date', 'student_email', 'full_name', 'course', 'price', 'real_price', 'key']) for i in invoices.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.date() + i.date, + i.bill.user.email, + i.bill.user.get_full_name(), + i.bill.course.title, + i.price, + i.real_price, + i.key, ]) return response \ No newline at end of file