import random from dj_language.field import LanguageField from django.contrib.auth.models import AbstractUser from django.db import models from django.utils.translation import gettext_lazy as _ from django.utils import timezone from phonenumber_field.modelfields import PhoneNumberField from utils.validators import validate_possible_number from apps.account.manager import UserManager class User(AbstractUser): class DeviceOs(models.TextChoices): android = 'android', 'android' apple = 'apple', 'apple' class UserType(models.TextChoices): PROFESSOR = 'professor', 'Professor' CLIENT = 'client', 'Client' STUDENT = 'student', "Student" ADMIN = 'admin', 'Admin' SUPER_ADMIN = 'super_admin', 'Super Admin' class GenderChoices(models.TextChoices): MALE = 'male', 'Male' FEMALE = 'female', 'Female' last_name = None first_name = None username = models.CharField(unique=True, null=True, blank=True, max_length=150) email = models.EmailField(unique=True, verbose_name="Email Address", help_text="Enter the user's email address.", null=True, blank=True) fullname = models.CharField(max_length=255, verbose_name="Full Name", help_text="Enter the full name of the user.", null=True, blank=True) birthdate = models.DateField(verbose_name=_('birthdate'), null=True, blank=True) avatar = models.ImageField(null=True, blank=True, upload_to='users/avatars/%Y/%m/') phone_number = PhoneNumberField( validators=[validate_possible_number], null=True, blank=True, verbose_name=_('Phone Number'), help_text="e.g., +49 151 12345678" ) language = LanguageField(null=True) gender = models.CharField(max_length=20, choices=GenderChoices.choices, null=True, blank=True, verbose_name=_('Gender'), help_text="Select the user's gender.") user_type = models.CharField(max_length=20, choices=UserType.choices, default=UserType.CLIENT, verbose_name="User Type", help_text="Type of the user.") date_joined = models.DateTimeField(auto_now_add=True, verbose_name="Date Joined", help_text="The date and time the user registered.") city = models.CharField(verbose_name=_('City'), max_length=255, null=True, blank=True) country = models.CharField(max_length=255, verbose_name=_('country'), null=True, blank=True) device_id = models.CharField(verbose_name=_('device id'), max_length=255, null=True, blank=True) device_os = models.CharField(choices=DeviceOs.choices, null=True, max_length=16) fcm = models.CharField(max_length=512, null=True, blank=True) is_staff = models.BooleanField(default=False) is_active = models.BooleanField(default=True, verbose_name="Active", help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.") deleted_at = models.DateTimeField(null=True, blank=True) info = models.TextField(verbose_name="Info", null=True, blank=True) skill = models.CharField(max_length=512, null=True, blank=True) objects = UserManager() EMAIL_FIELD = "email" USERNAME_FIELD = "email" REQUIRED_FIELDS = [] def __str__(self): username = self.email or self.fullname or self.device_id return f"{username}-({self.user_type})" def soft_delete(self): self.deleted_at = timezone.now() self.is_active = False self.fullname = f'{self.fullname}:deleted' number = str(random.randint(1000000000, 9999999999)) self.phone_number = f'{self.phone_number}:deleted{number}' self.email = f'{self.email}:deleted{number}' if self.email else None self.save() def save(self, *args, **kwargs): self.username = self.email if User.objects.filter(username=self.email).count(): self.username = f'{self.email}:{self.id}' return super().save(*args, **kwargs) def get_full_name(self): return self.fullname @property def is_guest(self): return self.email is None @property def user_type_based_on_groups(self): if self.groups.filter(name="Student Group").exists(): return self.UserType.STUDENT elif self.groups.filter(name="Professor Group").exists(): return self.UserType.PROFESSOR else: return self.UserType.CLIENT class Meta: ordering = ("-id",) verbose_name = "All Users" verbose_name_plural = "All Users" unique_together = ( 'email', 'device_id' ) class LoginHistory(models.Model): user = models.ForeignKey("account.User", on_delete=models.CASCADE, related_name='login_history') lat = models.FloatField(verbose_name=_('lat'), null=True, blank=True) lon = models.FloatField(verbose_name=_('lon'), null=True, blank=True) country = models.CharField(max_length=255, verbose_name=_('country'), null=True, blank=True) city = models.CharField(max_length=255, verbose_name=_('city'), null=True, blank=True) ip = models.CharField(max_length=255, null=True) timezone = models.CharField(max_length=100, null=True, blank=True) at_time = models.DateTimeField(auto_now_add=True)