from dateutil.relativedelta import relativedelta from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, AbstractUser, Group, PermissionsMixin from django.contrib.contenttypes.fields import GenericRelation from django.db import models from django.db.models import Sum from django.utils import timezone, formats from mptt.models import TreeForeignKey, TreeManyToManyField import pydash as _; _.map = _.map_; _.filter = _.filter_ from archilance import util from specializations.models import Specialization # from chat.models import NewMessage GENDERS = ( ('male', 'Мужской'), ('female', 'Женский'), ) class UserManager(BaseUserManager): def create_user(self, username, email, password=None, **kwargs): if not email: raise ValueError('Users must have an email address') user = self.model(username=username, email=UserManager.normalize_email(email),) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password): username = email user = self.create_user(username, email, password) user.is_superuser = True user.save(using=self._db) return user class ContractorUserManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(groups__name='Исполнители') class CustomerUserManager(models.Manager): def get_queryset(self): return super().get_queryset().filter(groups__name='Заказчики') class UserFinancialInfo(models.Model): RESIDENCIES = ( ('russian_resident', 'Резидент РФ'), ('non_russian_resident', 'Нерезидент РФ'), ('refugee', 'Беженец'), ('russian_stay_permit', 'Вид на жительство'), ) LEGAL_STATUSES = ( ('individual', 'Физическое лицо'), ('legal_entity', 'ИП и юридическое лицо'), ) address = models.CharField(max_length=1000) credit_card_number = models.CharField(max_length=50) date_of_birth = models.DateField() fio = models.CharField(max_length=255) inn = models.CharField(max_length=100) legal_status = models.CharField(max_length=30, choices=LEGAL_STATUSES) passport_issue_date = models.DateField() passport_issued_by = models.CharField(max_length=255) passport_number = models.CharField(max_length=10) passport_scan = models.ImageField(upload_to='users/contractors/') passport_series = models.CharField(max_length=6) phone = models.CharField(max_length=30) residency = models.CharField(max_length=50, choices=RESIDENCIES) subdivision_code = models.CharField(max_length=10) yandex_money = models.CharField(max_length=50) def __str__(self): return self.fio class Meta: verbose_name = 'Финансовая информация' verbose_name_plural = 'Финансовая информация' class ContractorResume(models.Model): resume_file = models.FileField(upload_to='users/resume/files/', null=True, blank=True) text = models.TextField(blank=True) def __str__(self): return str(self.pk) class Meta: verbose_name = 'Резюме' verbose_name_plural = 'Резюме' RESUME_TYPE_FILES = ( ('diplom', 'Дипломы/Сертификаты'), ('cro', 'Допуск CPO'), ) class ContractorResumeFiles(models.Model): description = models.TextField(blank=True) img = models.ImageField(upload_to='users/resume/images/') resume = models.ForeignKey(ContractorResume, related_name='resume_files') title = models.CharField(max_length=255,blank=True) type = models.CharField(max_length=50, choices=RESUME_TYPE_FILES, default='diplom') def __str__(self): return self.title class Meta: verbose_name = 'Файлы резюме' verbose_name_plural = 'Файлы резюме' class User(AbstractBaseUser, PermissionsMixin): STATUSES = ( ('free', 'Свободен'), ('busy', 'Занят'), ) avatar = models.ImageField(upload_to='users/avatars/', blank=True) contractor_answers = GenericRelation('projects.Answer', related_query_name='contractors') contractor_resume = models.OneToOneField(ContractorResume, related_name='contractor', blank=True, null=True) contractor_specializations = TreeManyToManyField(Specialization, related_name='contractors', blank=True) contractor_status = models.CharField(default='free', max_length=20, choices=STATUSES) created = models.DateTimeField(default=timezone.now) cro = models.BooleanField(default=False) date_joined = models.DateTimeField(default=timezone.now) date_of_birth = models.DateField(null=True, blank=True) email = models.EmailField(max_length=255, unique=True, db_index=True) financial_info = models.OneToOneField(UserFinancialInfo, related_name='user', blank=True, null=True) first_name = models.CharField(max_length=255, blank=True) gender = models.CharField(max_length=30, choices=GENDERS, blank=True, null=True) is_active = models.BooleanField(default=True) last_name = models.CharField(max_length=255, blank=True) last_time_visit = models.DateTimeField(default=timezone.now) location = TreeForeignKey('common.Location', related_name='users', null=True, blank=True) patronym = models.CharField(max_length=255, blank=True) phone = models.CharField(max_length=30, blank=True, null=True) phone2 = models.CharField(max_length=30, blank=True, null=True) rating = models.FloatField(default=0.0) skype = models.CharField(max_length=100, blank=True) username = models.CharField(max_length=50, unique=True) website = models.CharField(max_length=255, blank=True) def get_location(self): if self.location: if self.location.level == 3: return self.location.parent.parent.name + ', ' + self.location.name elif self.location.level == 2: return self.location.parent.name + ', ' + self.location.name elif self.location.level == 1: return self.location.name @property def is_staff(self): # return self.is_superuser return True def __str__(self): return self.email def get_short_name(self): return self.email def get_full_name(self): full_name = self.first_name + ' ' + self.last_name + ' ' + self.patronym return full_name or self.username def get_profile_image(self): return self.avatar def get_score(self): from wallets.models import InvoiceHistory current_sum_info = InvoiceHistory.objects.filter(user=self, type="score").aggregate(Sum('sum')) current_sum = current_sum_info['sum__sum'] or 0 return current_sum def summary(self): if self.date_of_birth: years = relativedelta(timezone.now(), util.to_local_datetime(self.date_of_birth)).years age = '%s %s' % (years, util.morph(years, ('год', 'года', 'лет'))) dob = formats.date_format(self.date_of_birth, 'DATE_FORMAT') else: age = dob = None return _.join(_.compact(( self.get_gender_display(), age, dob, )), ', ') USERNAME_FIELD = 'username' REQUIRED_FIELDS = [] objects = UserManager() contractor_objects = ContractorUserManager() customer_objects = CustomerUserManager() class Meta: verbose_name = 'Пользователь' verbose_name_plural = 'Пользователи' def is_contractor(self): return self.groups.filter(name='Исполнители').exists() def is_customer(self): return self.groups.filter(name='Заказчики').exists() def has_team(self): return self.is_contractor() and bool(util.get_related_or_none(self, 'team')) def is_owner_team(self): return Team.objects.filter(owner=self.pk).exists() def get_popular_specialization(self): from ratings.models import SpecializationRating rating = SpecializationRating.objects.filter(user=self).order_by('position').first() if rating: return rating.specialization.name class Team(models.Model): answers = GenericRelation('projects.Answer', related_query_name='teams') created = models.DateTimeField(default=timezone.now) name = models.CharField(max_length=255) owner = models.OneToOneField(User, related_name='team', blank=True, null=True) specializations = TreeManyToManyField(Specialization, related_name='teams', blank=True) contractors = models.ManyToManyField(User, limit_choices_to={'groups__name': 'Исполнители'}, related_name ='teams', blank=True) rating = models.FloatField(default=0.0) def __str__(self): return self.name class Meta: verbose_name = 'Команда' verbose_name_plural = 'Команды' class TeamInvitation(models.Model): contractor1 = models.ForeignKey(User, related_name='invites') contractor2 = models.ForeignKey(User, related_name='invited_by') def __str__(self): return '%s-%s' % (self.contractor1.username, self.contractor2.username) class Meta: verbose_name = 'Приглашение в команду' verbose_name_plural = 'Приглашения в команды' unique_together = ('contractor1', 'contractor2')