from django.db import models from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin from django.core.mail import send_mail from django.utils.encoding import force_bytes from django.template.loader import render_to_string from django.contrib.auth.tokens import default_token_generator from django.conf import settings from django.utils.http import urlsafe_base64_encode class Service(models.Model): name = models.CharField(max_length=20) description = models.CharField(max_length=100, blank=True, null=True) def __str__(self): return self.name class UserManager(BaseUserManager): def create_user(self, first_name, last_name, email, password=None, **extra_fields): """ Creates and saves a User with the given first name, last name, email, and password. """ if not email: raise ValueError('Users must have an email address') email = self.normalize_email(email) user = self.model( first_name=first_name, last_name=last_name, email=email, **extra_fields ) user.set_password(password) user.save(using=self._db) try: self.send_verification_email(user) except: print("Couldnot send verification email.") return user def create_superuser(self, first_name, last_name, email, password=None, **extra_fields): """ Creates and saves a superuser with the given first name, last name, email, and password. """ extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_active', True) if extra_fields.get('is_staff') is not True: raise ValueError('Superuser must have is_staff=True.') if extra_fields.get('is_superuser') is not True: raise ValueError('Superuser must have is_superuser=True.') return self.create_user(first_name, last_name, email, password, **extra_fields) def send_verification_email(self, user): # Generate the token and the uid for the verification URL token = default_token_generator.make_token(user) uid = urlsafe_base64_encode(force_bytes(user.pk)) verification_url = f"{settings.FRONTEND_URL}/verify-email/{uid}/{token}/" subject = "Verify Your Email Address" message = render_to_string('emails/verification_email.html', { 'user': user, 'verification_url': verification_url, }) send_mail( subject, message, settings.DEFAULT_FROM_EMAIL, [user.email], fail_silently=False, ) OPTIONS = [ ('NORMAL','Normal User'), ('SERVICE', 'Service Provider'), ('ADMIN', 'Admin User'), ] class User(AbstractBaseUser, PermissionsMixin): email = models.EmailField(unique=True) first_name = models.CharField(max_length=30) last_name = models.CharField(max_length=30) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) is_superuser = models.BooleanField(default=False) profile = models.ImageField(blank=True,null=True, upload_to="profile-images/") price = models.PositiveBigIntegerField(blank=True, null=True) bio = models.CharField(max_length=200, blank=True, null=True) member_since = models.DateTimeField(auto_now_add=True) updated_on = models.DateField(auto_now=True) service_offered = models.ForeignKey(Service, on_delete=models.CASCADE,blank=True,null=True) login_profile = models.CharField( max_length=15, choices=OPTIONS, default='NORMAL', ) USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['first_name', 'last_name','price','bio'] objects = UserManager() def __str__(self): return self.email def get_full_name(self): return f"{self.first_name} {self.last_name}" def get_short_name(self): return self.first_name class ServiceRequest(models.Model): client = models.ForeignKey(User,on_delete=models.CASCADE,related_name="client") service_provider = models.ForeignKey(User,on_delete=models.CASCADE,related_name="service_provider") agreed_price = models.DecimalField(max_digits=999,decimal_places=2 , default=0) service_hour = models.PositiveIntegerField(default=1) agreed_on = models.DateField(auto_now_add=True) is_approved = models.DateTimeField(blank=True, null=True) remarks = models.TextField(blank=True, null=True) is_completed = models.BooleanField(default=False) completed_date = models.DateTimeField(null=True,blank=True) service = models.ForeignKey(Service, on_delete=models.CASCADE, related_name="service_offered") def __str__(self): return self.service.name @property def get_full_price(self): return self.agreed_price * self.service_hour