# encoding=utf-8 import random from django.db import models from django.contrib.auth.models import BaseUserManager, AbstractBaseUser import datetime from django.db.models import SET_NULL from lms.regex import check_email from lms.settings import STATIC_ROOT, DOMAIN from lms.tools import random_string, random_int, out_date_format, get_client_ip import os from management.letters import sent_registration from storage.models import Storage import django.utils.timezone from django.core.files.base import File from django.utils.deconstruct import deconstructible from uuid import uuid4 ROLE = ( ('U', u'Студент школы'), ('T', u'Преподаватель'), ('M', u'Менеджер'), ('S', u'Руководитель'), ('S2', u'Куратор'), ('A', u'Администратор'), ('Ts', u'Тестовый пользователь'), ('F', u'Пользователь свободного счета') ) @deconstructible class PathAndRename(object): def __init__(self, sub_path): self.path = sub_path def __call__(self, instance, filename): ext = filename.split('.')[-1] # set filename as random string filename = '{}.{}'.format(uuid4().hex, ext) # return the whole path to the file return os.path.join(self.path, filename) path_and_rename = PathAndRename("personal_files") def insert_in_system(user, sent_letter=True): if sent_letter: sent_registration(user) user.subscription = Subscription.objects.create(owner=user) user.interactive_key = gen_interactive_key(user) user.save() def random_avatar(): ava_dir = os.path.join(STATIC_ROOT, 'img/avs') files = os.listdir(ava_dir) return os.path.join(ava_dir, random.choice(files)) class UserManager(BaseUserManager): def create_user(self, email, password=None, sent_letter=True): if not email: raise ValueError(u"Пользователь должен иметь email") if not check_email(email): raise ValueError(u"Email введен не верно") user = self.model(email=email) user.set_password(password) user.token = random_string(length=10, postfix=user.email) user.save(using=self._db) insert_in_system(user, sent_letter=sent_letter) return user def create_superuser(self, email, password): user = self.create_user(email, password=password) user.is_admin = True user.is_active = True user.superuser = True user.is_staff = True user.token = random_string(length=10, postfix=user.email) user.save(using=self._db) return user def __unicode__(self): return u'%s %s' % (self.get_short_name(), self.email) def get_activate_time(): return datetime.datetime.now() + datetime.timedelta(days=7) def gen_interactive_key(user): # 1 Надпись ID # 2 id в системе # 3 # # 4 5 случайных чисел return 'ID{0}-{1}'.format(user.id, random_int(length=5)) class User(AbstractBaseUser): STATUS_CHOICES = ( ('ON', 'on-line'), ('OFF', 'off-line') ) REG_STATUS = ( ('1', 'Пароль'), ('2', 'О себе'), ('3', 'Фото'), ('4', 'Закончена') ) PRIVATE = ( ('A', 'Всему интернету'), ('U', 'Только пользователям системы'), ('L', 'По прямой ссылке'), ('B', 'Только мне') ) SOURCE = ( ('S', 'Органично'), ('B', 'Привлечен') ) #sync = models.BooleanField(verbose_name=u'Синхронизирован', default=False) #sync_date = models.DateTimeField(verbose_name=u'Дата постановки на синхронизацию', blank=True, null=True) block = models.BooleanField(verbose_name=u'Заблокировать', default=False) refer = models.CharField(verbose_name=u'Источник', max_length=1, choices=SOURCE, default='S', null=True) refer_source = models.CharField(verbose_name=u'Источник пользователя', blank=True, max_length=255, default='') traf_source = models.ForeignKey('TrafHistory', verbose_name=u'Обращение', blank=True, null=True) private = models.CharField(verbose_name=u'Приватность профиля', max_length=1, choices=PRIVATE, default='A') customer = models.BooleanField(verbose_name=u'Покупатель', default=False) interactive_key = models.CharField(verbose_name=u'Интерактивый ключ', max_length=255, blank=True) deactivate = models.BooleanField(verbose_name=u'Не давать новых студентов', default=False) delay = models.BooleanField(verbose_name=u'Могут быть задержки', default=False, help_text=u'Если возможны задержки с проверками') delay_description = models.TextField(verbose_name=u'Повод просрочки', blank=True) delay_date = models.DateTimeField(verbose_name=u'Задержка до. Не включая этот день.', blank=True, default=datetime.datetime.now(), null=True) email = models.EmailField(verbose_name='email', max_length=255, blank=True, db_index=True, unique=True, help_text=u'Будьте аккуратны. Менять почту можно. Но только если очень нужно.') changed_email = models.EmailField(verbose_name=u'Ящик на замену', blank=True, null=True) phone = models.CharField(verbose_name=u'Телефон', max_length=255, default='', blank=True) back_phone = models.CharField(verbose_name=u'Предидущий телефон', max_length=255, default='', blank=True) status = models.CharField(max_length=9, choices=STATUS_CHOICES, default='ON') in_role = models.CharField(verbose_name=u'Роль', choices=ROLE, max_length=2, default='U') unique_role = models.CharField(verbose_name=u'Уникальная роль', max_length=255, blank=True, default='') city = models.CharField(verbose_name=u'Город', max_length=255, default='', blank=True) b_day = models.DateField(verbose_name=u'День рождения', null=True, blank=True) token = models.CharField(max_length=255, default='', blank=True) activate_time = models.DateTimeField(verbose_name=u"Активировать до", default=get_activate_time) reg_status = models.CharField(verbose_name=u'Статус регистрации', choices=REG_STATUS, max_length=1, default='1') is_active = models.BooleanField(default=False) is_admin = models.BooleanField(default=False, editable=False) is_staff = models.BooleanField(default=False, editable=False) objects = UserManager() avatar = models.CharField(verbose_name=u"Ключ аватара", max_length=255, blank=True, default='') in_avatar = models.ImageField(verbose_name=u'Наш аватар', blank=True, null=True, editable=False, upload_to='in_ava') fname = models.CharField(verbose_name=u"Фамилия", max_length=255, blank=True, default='') name = models.CharField(verbose_name=u"Имя", max_length=255, blank=True, default='') oname = models.CharField(verbose_name=u"Отчество", max_length=255, blank=True, default='') # skype = models.CharField(max_length=300, blank=True, default='') facebook = models.CharField(default='', max_length=255, blank=True) vk = models.CharField(max_length=255, default='', blank=True) linkedin = models.CharField(max_length=255, default='', blank=True) odnoklassniki = models.CharField(max_length=255, default='', blank=True) # last_time = models.DateTimeField(verbose_name=u'Последняя активность', default=datetime.datetime.now) date_joined = models.DateTimeField(default=datetime.datetime.now) last_ip = models.ForeignKey('UserRequest', verbose_name=u'Последний IP', blank=True, null=True, related_name='user_last_ip', on_delete=SET_NULL) USERNAME_FIELD = 'email' def save(self, *args, **kwargs): if self.in_role in ['A', 'S2'] and not self.is_admin: self.is_admin = True self.is_staff = True if self.in_role in ['M']: self.is_staff = True if not self.interactive_key: self.interactive_key = gen_interactive_key(self) super(User, self).save(*args, **kwargs) def get_ip_len(self): UserRequest.objects.filter(user=self).count() def set_request_data(self, request): ip = get_client_ip(request) try: _request = UserRequest.objects.get(ip=ip, user=self) except UserRequest.DoesNotExist: _request = UserRequest.objects.create(ip=ip, user=self) _request.new_count(request) self.last_ip = _request self.save() def get_ip(self): return self.last_ip.ip if self.last_ip else None def get_activation_url(self): return u'{3}/access/activate/?step=1&token={0}&email={1}'.format(self.token, self.email, self.reg_status, DOMAIN) def _set_to_sync(self): self.sync = False self.sync_date = datetime.datetime.now() self.save() def _set_synced(self): self.sync = True self.sync_date = None self.save() def change_token(self): self.token = random_string(length=10, postfix=self.email) self.save() def get_status_point(self): return {'title': self.get_status_display(), 'color': 'green' if self.status == 'ON' else 'red', 'point': 'glyphicon glyphicon-ok-sign' if self.status == 'ON' else 'glyphicon glyphicon-remove-sign'} def get_full_data(self): return self.full_data() def full_data(self): return 'Имя: {0} - Телефон: {1} - Почта: {2}'.format(self.get_full_name(), self.get_phone(), self.email) def get_name(self): if self.name: return self.name else: return 'Без имени' def get_face(self): return {'full_name': self.get_full_name(), 'short_name': self.get_short_name(), 'name': self.name if self.name else '', 'fname': self.fname if self.fname else '', 'oname': self.oname if self.oname else '', 'email': self.email, 'phone': self.get_phone(), 'ava': self.get_image_url(), 'date_joined': out_date_format(self.date_joined), 'status': self.get_status_point(), 'id': self.id, 'interactive_key': self.interactive_key, 'is_staff': self.is_staff or self.is_admin, 'role': self.unique_role if self.unique_role else self.get_in_role_display(), 'is_unique_role': bool(self.unique_role), 'profile': self.get_profile()} def get_username(self): return self.get_short_name() def get_image_url(self, type_in=None): try: image = Storage.objects.get(key=self.avatar) except Storage.DoesNotExist: if not self.in_avatar: self.in_avatar.save('ava', File(open(random_avatar(), 'rb')), save=True) return '{0}/{1}'.format(DOMAIN, self.in_avatar.url) else: try: image = image.get_url(type_in) except IOError: if not self.in_avatar: self.in_avatar.save('ava', File(open(random_avatar(), 'rb')), save=True) return '{0}/{1}'.format(DOMAIN, self.in_avatar.url) return image def clean_image(self): self.avatar = '' self.save() def get_phone(self): return self.phone def get_back_phone(self): return self.back_phone def get_full_name(self): result = u"" # Если есть фамилия пишем: Фамилия Имя Отчество if self.fname: result += u"%s" % self.fname if self.name: result += u" %s" % self.name if self.oname: result += u" %s" % self.oname if result: return result else: return self.email def get_short_name(self): result = u"" # Если есть фамилия пишем: Фамилия И.О. if self.fname: result += u"%s" % self.fname if self.name: result += u" %s." % self.name[0].upper() if self.oname: result += u" %s." % self.oname[0].upper() # Если нет фамилии пишем: Имя Отчество elif not self.fname and self.name: if self.name: result += u"%s" % self.name if self.oname: result += u" %s" % self.oname if result: return result else: return self.email def has_perm(self, perm, obj=None): return True def has_module_perms(self, app_label): return True def check_subscription(self, right): return Subscription.objects.get_or_create(owner=self)[0].check_right(right) def get_profile(self): return u'{0}/{1}'.format(DOMAIN, self.interactive_key) def __unicode__(self): return u'%s:%s' % (self.id, self.get_short_name()) def __str__(self): return '%s:%s' % (self.id, self.get_short_name()) def name_to_html(self, user): if user == self: return u"Вы" else: return u"%s" \ % (self.id, self.get_short_name()) class Meta: verbose_name = u"Пользователя" verbose_name_plural = u"Пользователи" class UserRequest(models.Model): # Информация о сессиях пользователей при авторизации ip = models.CharField(verbose_name=u'IP', max_length=255) user = models.ForeignKey(User, verbose_name=u'Пользователь') count = models.IntegerField(verbose_name=u'Количество использований', default=0) date = models.DateTimeField(verbose_name=u'Дата', default=datetime.datetime.now) def __str__(self): return self.ip def new_count(self, request): self.count += 1 UserRequestData.objects.create(row=self, data=request) self.save() class Meta: verbose_name = u'Данные сессии при авторизации' verbose_name_plural = u'Данные сессий при авторизации' class UserRequestData(models.Model): # Содержимое сессии пользователя row = models.ForeignKey(UserRequest, verbose_name=u'Запрос') data = models.TextField(verbose_name=u'Данные') date = models.DateTimeField(verbose_name=u'Дата', default=datetime.datetime.now) def __str__(self): return str(self.row) class Meta: verbose_name = u'Данные запроса' verbose_name_plural = u'Данные запроса' class Subscription(models.Model): # Подписки owner = models.OneToOneField(User, verbose_name=u"Владелец", unique=True, related_name='rights_owner') news = models.BooleanField(verbose_name=u"Подписка на новости", default=True) teacher = models.BooleanField(verbose_name=u'Ответы преподователя', default=True) new_comments = models.BooleanField(verbose_name=u'Ответы на комментарии', default=True) send_sms = models.BooleanField(verbose_name=u'Отправлять sms', default=False) courses = models.BooleanField(verbose_name=u'Новые курсы', default=True) def __str__(self): return "%s: %s" % (self.id, self.owner) def __unicode__(self): return u"%s: %s" % (self.id, self.owner) def check_right(self, right): # Проверка указанного права для пользователя return self.right_map(right) def set_right(self, right, value): # Установка права if right == 'news': self.news = value elif right == 'teacher': self.teacher = value elif right == 'send_sms': self.send_sms = value elif right == 'courses': self.courses = value elif right == 'new_comments': self.new_comments = value self.save() def set_default_values(self): # Установка дефолтных значений for field in self._meta.fields: if field.has_default: self.set_right(field.name, field.default) def right_map(self, right): # Карта проверки прав __right_map = { 'news': self.news, 'teacher': self.teacher, 'send_sms': self.send_sms, 'courses': self.courses, 'new_comments': self.new_comments } if right in __right_map: return __right_map[right] else: return __right_map class Meta: verbose_name = u"Подписка" verbose_name_plural = u"Подписки" class ActionJ(models.Model): ACTION_TYPE = ( ('B', 'b-default'), ('P', 'b-primary'), ('S', 'b-success'), ('I', 'b-info'), ('W', 'b-warning'), ('D', 'b-danger') ) student = models.ForeignKey(User, verbose_name=u'Студент') a_type = models.CharField(verbose_name=u'Тип события', choices=ACTION_TYPE, max_length=1, default='B') place = models.CharField(verbose_name=u'Место создания события', max_length=100) date = models.DateTimeField(verbose_name=u'Время создания', default=django.utils.timezone.now) text = models.TextField(verbose_name=u'Текст сообщения') def __str__(self): return '%s %s %s' % (self.get_a_type_display(), self.place, self.date) def __unicode__(self): return u'%s %s %s' % (self.get_a_type_display(), self.place, self.date) class Meta: verbose_name = u'Журнал активности' verbose_name_plural = u'Журналы активностей' class TrafSource(models.Model): on = models.BooleanField(verbose_name=u'Ативен', default=True) url = models.URLField(verbose_name=u'Источник трафика') token = models.CharField(verbose_name=u'Токен доступа', max_length=255, editable=False) token_start = models.DateTimeField(verbose_name=u'Точка отсчета жизни токена', editable=False, null=True) live_time = models.IntegerField(verbose_name=u'Время жизни токена', blank=True, help_text=u'Указывается в часах. пустое поле - пожизненно', null=True) date_start = models.DateTimeField(verbose_name=u'Дата запуска источника', default=datetime.datetime.now) def __str__(self): return '%s' % self.url def __unicode__(self): return u'%s' % self.url def save(self, *args, **kwargs): if not self.token: self.token = random_string(length=20) self.token_start = datetime.datetime.now() super(TrafSource, self).save(*args, **kwargs) class Meta: verbose_name = u'Источник трафика' verbose_name_plural = u'Источники трафика' class TrafTokenHistory(models.Model): token = models.CharField(verbose_name=u'Токен', max_length=255, editable=False) live_time = models.IntegerField(verbose_name=u'Время жизни', help_text=u'В часах', editable=False) date_start = models.DateTimeField(verbose_name=u'Дата установки токена', editable=False) date_end = models.DateTimeField(verbose_name=u'Дата отключения', editable=False) source = models.ForeignKey(TrafSource, verbose_name=u'Использующий источник', editable=False) def __str__(self): return '%s %s:%s %s' % (self.token, self.date_start, self.date_end, self.sources) def __unicode__(self): return u'%s %s:%s %s' % (self.token, self.date_start, self.date_end, self.sources) class Meta: verbose_name = u'История смены токена' verbose_name_plural = u'Истории смены токенов' class TrafHistory(models.Model): TRAF_ACTION = ( ('G', 'Получение данных'), ('D', 'Запись данных'), ('C', 'Создание пользователя'), ('O', 'Создание счета') ) action = models.CharField(verbose_name=u'Действие', choices=TRAF_ACTION, max_length=1) source = models.ForeignKey(TrafSource, verbose_name=u'Источник запроса') token = models.CharField(verbose_name=u'Используемый токен', max_length=255, null=True) data = models.TextField(verbose_name=u'Данные в запросе') result = models.BooleanField(verbose_name=u'Результат запроса', default=False) result_description = models.CharField(verbose_name=u'Описание результата', max_length=255, blank=True) date = models.DateTimeField(verbose_name=u'Дата обращения', default=datetime.datetime.now) def __str__(self): return '%s %s %s' % (self.source, self.action, self.result) def __unicode__(self): return u'%s %s %s' % (self.source, self.action, self.result) class Meta: verbose_name = u'Обращение источника' verbose_name_plural = u'Обращения источников' class Document(models.Model): DOC_STATUS = ( ('W', u'На оформлении'), ('F', u'Оформлен') ) title = models.CharField(verbose_name=u'Заголовок', max_length=255) status = models.CharField(verbose_name=u'Статус', choices=DOC_STATUS, default='W', editable=False, max_length=1) user = models.ForeignKey(User, verbose_name=u'Пользователь') date = models.DateField(verbose_name=u'Дата заключения', default=datetime.datetime.now) file = models.FileField(verbose_name=u'Скан', upload_to='documents', null=True, blank=True) in_date = models.DateTimeField(verbose_name=u'Дата добавления', default=datetime.datetime.now, editable=False) def __str__(self): return u'%s %s' % (self.title, self.date) def __unicode__(self): return u'%s %s' % (self.title, self.date) def save(self, *args, **kwargs): if self.file and self.status != 'F': self.status = 'F' elif not self.file and self.status != 'W': self.status = 'W' super(Document, self).save(*args, **kwargs) class Meta: verbose_name = u'Документ' verbose_name_plural = u'Документы' class Questionnaire(models.Model): GENDER = ( ('M', 'Мужчина'), ('W', 'Женщина') ) EXP = ( ('1', 'Только начинаю'), ('2', 'Да, менее года'), ('3', 'Да, 1-2 года'), ('4', 'Да, более 2 лет') ) AIM = ( ('1', 'Да, в офисе'), ('2', 'Да, свой проект'), ('3', 'Да, на фрилансе'), ('4', 'Нет, изучаю для себя') ) AGE = ( ('1', 'до 18'), ('2', '18-25'), ('3', '25-30'), ('4', '30-40'), ('5', 'больше 40') ) FULLY = ( ('1', 'Флаги'), ('2', 'Свободный ответ'), ('3', 'Завершено') ) fully = models.CharField(verbose_name=u'Стадия', max_length=1, choices=FULLY, default=1) # Завершенность заполения steps = models.IntegerField(verbose_name=u'Количество показов', default=0, help_text=u'Количество показов для заполнения') user = models.ForeignKey(User, verbose_name=u'Пользователь') male = models.CharField(verbose_name=u'Пол', choices=GENDER, max_length=1, null=True, blank=True) city = models.CharField(verbose_name=u'Город', max_length=255, null=True, blank=True) experience = models.CharField(verbose_name=u'Опыт', max_length=1, choices=EXP, null=True, blank=True) aim = models.CharField(verbose_name=u'Цель обучения', max_length=1, choices=AIM, null=True, blank=True) age = models.CharField(verbose_name=u'Возраст', max_length=1, choices=AGE, null=True, blank=True) description = models.TextField(verbose_name=u'Свободны ответ', blank=True) def __str__(self): return u'%s %s' % (self.user, self.get_fully_display()) def __unicode__(self): return u'%s %s' % (self.user, self.get_fully_display()) class Meta: verbose_name = u'Акета' verbose_name_plural = u'Анкеты' #class UserSync(models.Model): # user = models.ForeignKey(User, verbose_name=u'Синхронизируемый') # date = models.DateTimeField(verbose_name=u'Дата начала', default=datetime.datetime.now) # data = models.TextField(verbose_name=u'Сырые данные', blank=True, default='') # f_date = models.DateTimeField(verbose_name=u'Дата завершения процеса', blank=True, null=True) # source = models.CharField(verbose_name=u'Источник синхронизации', max_length=255) # dist = models.CharField(verbose_name=u'Получатель синхронизации', max_length=255) # result = models.BooleanField(verbose_name=u'Результат синхронизации', default=False) # def __str__(self): # return '%s %s %s' % (self.user, self.f_date, self.result) # def __unicode__(self): # return u'%s %s %s' % (self.user, self.f_date, self.result) # def good_sync(self): # self.f_date = datetime.datetime.now() # self.result = True # self.save() # self.user._set_synced() # def fail_sync(self): # self.f_date = datetime.datetime.now() # self.result = False # self.save() # class Meta: # verbose_name = u'Задача синхронизации' # verbose_name_plural = u'Задачи синхронизации'