492 lines
15 KiB
Python
492 lines
15 KiB
Python
from collections.abc import Iterable
|
|
import datetime
|
|
import random
|
|
import string
|
|
|
|
# from manage_wallets.models import Wallet, Transaction, TransactionStatus, TransactionType
|
|
from django.conf import settings
|
|
from django.contrib.auth import get_user_model
|
|
from django.contrib.auth.models import AbstractUser, BaseUserManager
|
|
from django.db import models
|
|
from django.utils import timezone
|
|
from django.utils.text import slugify
|
|
from phonenumber_field.modelfields import PhoneNumberField
|
|
|
|
# from manage_subscriptions.models import Subscription
|
|
from goodtimes.utils import RandomGenerator
|
|
from .resource_action import (
|
|
PRINCIPAL_TYPE_EVENT_USER,
|
|
PRINCIPAL_TYPE_EVENT_MANAGER,
|
|
PRINCIPAL_TYPE_FREE_USER,
|
|
)
|
|
|
|
from .utils import UserContext
|
|
from django.core.validators import MaxValueValidator, MinValueValidator, RegexValidator
|
|
|
|
|
|
class BaseModel(models.Model):
|
|
active = models.BooleanField(default=True)
|
|
deleted = models.BooleanField(default=False)
|
|
created_by = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
related_name="%(class)s_created",
|
|
on_delete=models.CASCADE,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
created_on = models.DateTimeField(auto_now_add=True)
|
|
modified_by = models.ForeignKey(
|
|
settings.AUTH_USER_MODEL,
|
|
related_name="%(class)s_modified",
|
|
on_delete=models.CASCADE,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
modified_on = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
|
|
class MasterModel(models.Model):
|
|
name = models.CharField(max_length=255)
|
|
label = models.CharField(max_length=255, null=True, blank=True)
|
|
slug = models.SlugField(max_length=255, null=True, blank=True)
|
|
sort_order = models.IntegerField(blank=True, null=True)
|
|
small_image_url = models.ImageField(blank=True, null=True)
|
|
large_image_url = models.ImageField(blank=True, null=True)
|
|
active = models.BooleanField(default=True)
|
|
deleted = models.BooleanField(default=False)
|
|
created_by = models.SmallIntegerField(blank=True, null=True)
|
|
created_on = models.DateTimeField(auto_now_add=True)
|
|
modified_by = models.SmallIntegerField(blank=True, null=True)
|
|
modified_on = models.DateTimeField(auto_now=True)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
def __str__(self):
|
|
return f"{self.name}"
|
|
|
|
def save(self, *args, **kwargs):
|
|
# Generate a slug from the name field
|
|
self.slug = slugify(self.name)
|
|
return super().save(*args, **kwargs)
|
|
|
|
|
|
class IAmPrincipalType(MasterModel):
|
|
class Meta:
|
|
db_table = "iam_principal_type"
|
|
|
|
@classmethod
|
|
def get_principal_type(cls, type):
|
|
return cls.objects.filter(name=type).first()
|
|
|
|
|
|
class IAmPrincipalSource(MasterModel):
|
|
class Meta:
|
|
db_table = "iam_principal_source"
|
|
|
|
|
|
class IAmAppAction(MasterModel):
|
|
class Meta:
|
|
db_table = "iam_app_action"
|
|
|
|
|
|
class IAmAppResource(MasterModel):
|
|
action = models.ManyToManyField(
|
|
IAmAppAction,
|
|
through="IAmAppResourceActionLink",
|
|
related_name="app_resource_action",
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_app_resource"
|
|
|
|
|
|
class IAmRoleAppResourceActionLinkManager(models.Manager):
|
|
def generate_app_resource_action_data(self):
|
|
"""
|
|
Generate a dictionary mapping resource names to associated actions.
|
|
Returns:
|
|
dict: A dictionary with resource names as keys and nested dictionaries
|
|
where action IDs are keys and action names are values.
|
|
Example:
|
|
{
|
|
"res1": {1: "a1", 2: "a2"},
|
|
"res2": {3: "a1", 4: "a2"}
|
|
}
|
|
"""
|
|
app_resource_action = self.select_related("app_resource", "app_action").all()
|
|
resource_action_link = {}
|
|
for item in app_resource_action:
|
|
resource = item.app_resource.name
|
|
action = item.app_action.name
|
|
id = item.id
|
|
if resource in resource_action_link:
|
|
resource_action_link[resource][id] = action
|
|
else:
|
|
resource_action_link[resource] = {id: action}
|
|
# print(resource_action_link)
|
|
return resource_action_link
|
|
|
|
|
|
class IAmAppResourceActionLink(models.Model):
|
|
app_resource = models.ForeignKey(
|
|
IAmAppResource,
|
|
related_name="resource_action_link_app_resource",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
app_action = models.ForeignKey(
|
|
IAmAppAction,
|
|
related_name="resource_action_link_app_action",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
objects = IAmRoleAppResourceActionLinkManager()
|
|
|
|
class Meta:
|
|
db_table = "iam_app_resource_action_link"
|
|
|
|
def __str__(self):
|
|
return f"{self.app_resource.name}: {self.app_action.name}"
|
|
|
|
|
|
class IAmRole(MasterModel):
|
|
app_resource_action = models.ManyToManyField(
|
|
IAmAppResourceActionLink,
|
|
through="IAmRoleAppResourceActionLink",
|
|
related_name="role_app_resource_action",
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_role"
|
|
|
|
|
|
class IAmRoleAppResourceActionLink(models.Model):
|
|
role = models.ForeignKey(
|
|
IAmRole,
|
|
related_name="role_app_resource_action_link_role",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
app_resource_action = models.ForeignKey(
|
|
IAmAppResourceActionLink,
|
|
related_name="role_app_resource_action_link_app_resource_action",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_role_app_resource_action_link"
|
|
|
|
|
|
class IAmPrincipalGroup(MasterModel):
|
|
role = models.ManyToManyField(
|
|
IAmRole, through="IAmPricipalGroupRoleLink", related_name="principal_group_role"
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_group"
|
|
|
|
|
|
class IAmPricipalGroupRoleLink(models.Model):
|
|
principal_group = models.ForeignKey(
|
|
IAmPrincipalGroup,
|
|
related_name="role_link_principal_group",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
role = models.ForeignKey(
|
|
IAmRole, related_name="role_link_role", on_delete=models.CASCADE
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_group_role_link"
|
|
|
|
|
|
class IAmPrincipalManager(BaseUserManager):
|
|
def create_user(self, email, password=None, **extra_fields):
|
|
if not email:
|
|
raise ValueError("The Email field must be set")
|
|
email = self.normalize_email(email)
|
|
user = self.model(email=email, **extra_fields)
|
|
user.set_password(password)
|
|
user.save(using=self._db)
|
|
return user
|
|
|
|
def create_superuser(self, email, password=None, **extra_fields):
|
|
extra_fields.setdefault("username", email)
|
|
extra_fields.setdefault("is_staff", True)
|
|
extra_fields.setdefault("is_superuser", True)
|
|
# extra_fields.setdefault("phone_no", "+919978895465")
|
|
extra_fields.setdefault("gender", "M")
|
|
extra_fields.setdefault("referral_code", f"admin_{random.randint(10, 100000)}")
|
|
extra_fields.setdefault("date_of_birth", timezone.now())
|
|
extra_fields.setdefault("created_by", None)
|
|
extra_fields.setdefault("created_on", timezone.now())
|
|
extra_fields.setdefault("modified_by", None)
|
|
extra_fields.setdefault("modified_on", timezone.now())
|
|
return self.create_user(email, password, **extra_fields)
|
|
|
|
|
|
class IAmPrincipal(AbstractUser):
|
|
principal_type = models.ForeignKey(
|
|
IAmPrincipalType,
|
|
related_name="principals_type",
|
|
null=True,
|
|
on_delete=models.PROTECT,
|
|
)
|
|
principal_source = models.ForeignKey(
|
|
IAmPrincipalSource,
|
|
related_name="principals_source",
|
|
on_delete=models.CASCADE,
|
|
null=True,
|
|
)
|
|
principal_resource = models.ManyToManyField(
|
|
IAmAppResource,
|
|
through="IAmPrincipalResourceLink",
|
|
related_name="principal_resources",
|
|
)
|
|
email = models.EmailField(unique=True)
|
|
gender = models.CharField(max_length=5, blank=True, null=True)
|
|
date_of_birth = models.DateField(blank=True, null=True)
|
|
phone_no = PhoneNumberField(blank=True, null=True)
|
|
address_line1 = models.TextField(blank=True, null=True)
|
|
address_line2 = models.TextField(blank=True, null=True)
|
|
city = models.CharField(max_length=100, blank=True, null=True)
|
|
state = models.CharField(max_length=100, blank=True, null=True)
|
|
country = models.CharField(max_length=100, blank=True, null=True)
|
|
post_code = models.CharField(max_length=100, blank=True, null=True)
|
|
profile_photo = models.ImageField(upload_to="profile", blank=True, null=True)
|
|
phone_verified = models.BooleanField(default=False)
|
|
email_verified = models.BooleanField(default=False)
|
|
referral_code = models.CharField(max_length=50, null=True, blank=True)
|
|
apple_id = models.CharField(max_length=255, null=True, blank=True)
|
|
player_id = models.CharField(max_length=255, null=True, blank=True)
|
|
referred_by = models.ForeignKey(
|
|
"self",
|
|
null=True,
|
|
blank=True,
|
|
related_name="referrals",
|
|
on_delete=models.SET_NULL,
|
|
)
|
|
created_by = models.ForeignKey(
|
|
"self",
|
|
null=True,
|
|
blank=True,
|
|
related_name="creations",
|
|
on_delete=models.SET_NULL,
|
|
)
|
|
created_on = models.DateTimeField(auto_now_add=True)
|
|
modified_by = models.ForeignKey(
|
|
"self",
|
|
null=True,
|
|
blank=True,
|
|
related_name="modifications",
|
|
on_delete=models.SET_NULL,
|
|
)
|
|
modified_on = models.DateTimeField(auto_now=True)
|
|
deleted = models.BooleanField(default=False)
|
|
principal_group = models.ManyToManyField(
|
|
IAmPrincipalGroup,
|
|
through="IAmPrincipalGroupLink",
|
|
related_name="principal_groups",
|
|
)
|
|
register_complete = models.BooleanField(default=False)
|
|
linkedin_profile = models.URLField(
|
|
verbose_name="Principal LinkedIn",
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
instagram_profile = models.URLField(
|
|
verbose_name="Principal Instagram",
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
youtube_profile = models.URLField(
|
|
verbose_name="Principal Youtube",
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
facebook_profile = models.URLField(
|
|
verbose_name="Principal Facebook",
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
website = models.URLField(
|
|
verbose_name="Website",
|
|
max_length=200,
|
|
blank=True,
|
|
null=True,
|
|
)
|
|
|
|
USERNAME_FIELD = "email"
|
|
REQUIRED_FIELDS = []
|
|
|
|
objects = IAmPrincipalManager()
|
|
|
|
class Meta:
|
|
db_table = "iam_principal"
|
|
|
|
def __str__(self):
|
|
return f"{self.email}"
|
|
|
|
|
|
class IAmPrincipalExtendedData(models.Model):
|
|
principal = models.OneToOneField(
|
|
IAmPrincipal,
|
|
related_name="extended_data",
|
|
on_delete=models.CASCADE,
|
|
help_text="The principal user to which this extended data is related."
|
|
)
|
|
is_onboarded = models.BooleanField(
|
|
default=False,
|
|
help_text="Indicates whether the user was onboarded by an admin."
|
|
)
|
|
is_transferred = models.BooleanField(
|
|
default=False,
|
|
help_text="Indicates whether the account has been transferred to the user."
|
|
)
|
|
transferred_on = models.DateTimeField(
|
|
null=True,
|
|
blank=True,
|
|
help_text="The date and time when the account was transferred to the user."
|
|
)
|
|
pwd_changed_post_transfer = models.BooleanField(default=False, help_text="Indicates if the user changed their password after the account was transferred.")
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_extended_data"
|
|
|
|
def __str__(self):
|
|
return f"Extended Data for {self.principal}"
|
|
|
|
def save(self, *args, **kwargs):
|
|
if self.is_transferred and self.transferred_on is None:
|
|
self.transferred_on = datetime.datetime.now()
|
|
super().save(*args, **kwargs)
|
|
|
|
class IAmPrincipalResourceLink(models.Model):
|
|
principal = models.ForeignKey(
|
|
IAmPrincipal,
|
|
related_name="principal_resource_link_principal",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
principal_resource = models.ForeignKey(
|
|
IAmAppResource,
|
|
related_name="principal_resource_link_resource",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_resource_group_link"
|
|
|
|
|
|
class IAmPrincipalGroupLink(models.Model):
|
|
principal = models.ForeignKey(
|
|
IAmPrincipal,
|
|
related_name="principal_group_link_principal",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
principal_group = models.ForeignKey(
|
|
IAmPrincipalGroup,
|
|
related_name="principal_group_link_group",
|
|
on_delete=models.CASCADE,
|
|
)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_principal_group_link"
|
|
|
|
|
|
class IAmPrincipalMerchant(BaseModel):
|
|
principal = models.OneToOneField(
|
|
IAmPrincipal, related_name="principal_merchant", on_delete=models.CASCADE
|
|
)
|
|
|
|
def __str__(self):
|
|
return self.principal.email
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_merchant"
|
|
|
|
|
|
class IAmPrincipalOtp(models.Model):
|
|
principal = models.ForeignKey(
|
|
IAmPrincipal, related_name="principal_otp", on_delete=models.CASCADE
|
|
)
|
|
otp_code = models.CharField(max_length=4)
|
|
otp_purpose = models.CharField(max_length=50, null=True, blank=True)
|
|
valid_till = models.DateTimeField()
|
|
is_used = models.BooleanField(default=False)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_otp"
|
|
|
|
def __str__(self):
|
|
return f"{self.principal.phone_no}:{self.otp_code} : {self.otp_purpose}"
|
|
|
|
def save(self, *args, **kwargs):
|
|
if not self.pk:
|
|
self.otp_code = RandomGenerator.random_otp()
|
|
self.valid_till = timezone.now() + timezone.timedelta(
|
|
minutes=settings.OTP_EXPIRE_TIME
|
|
)
|
|
super(IAmPrincipalOtp, self).save(*args, **kwargs)
|
|
|
|
def is_expired(self):
|
|
return timezone.now() >= self.valid_till
|
|
|
|
|
|
class IAmPrincipalBiometric(BaseModel):
|
|
principal = models.ForeignKey(
|
|
IAmPrincipal, related_name="principal_biometric", on_delete=models.CASCADE
|
|
)
|
|
biometric_type = models.CharField(max_length=100)
|
|
biometric_data = models.CharField(max_length=255)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_biometric"
|
|
|
|
def __str__(self):
|
|
return f"{self.principal.first_name}:{self.biometric_type}"
|
|
|
|
|
|
class IAmPrincipalLocation(BaseModel):
|
|
principal = models.OneToOneField(
|
|
IAmPrincipal, related_name="principal_location", on_delete=models.CASCADE
|
|
)
|
|
latitude = models.DecimalField(max_digits=18, decimal_places=15)
|
|
longitude = models.DecimalField(max_digits=18, decimal_places=15)
|
|
|
|
class Meta:
|
|
db_table = "iam_principal_location"
|
|
|
|
def __str__(self):
|
|
return f"{self.principal.first_name}:{self.latitude}, {self.longitude}"
|
|
|
|
|
|
class AppType(models.TextChoices):
|
|
ANDROID = "android", "android"
|
|
IOS = "ios", "ios"
|
|
|
|
|
|
class AppVersion(models.Model):
|
|
version = models.CharField(
|
|
max_length=10, validators=[RegexValidator(r"^\d+\.\d+\.\d+$")]
|
|
)
|
|
force_upgrade = models.BooleanField(
|
|
default=False,
|
|
help_text="Indicates whether a force upgrade is needed for this app version.",
|
|
)
|
|
recommend_upgrade = models.BooleanField(
|
|
default=False,
|
|
help_text="Indicates whether a recommend upgrade is needed for this app version.",
|
|
)
|
|
app_type = models.CharField(max_length=10, choices=AppType.choices)
|
|
|
|
class Meta:
|
|
db_table = "app_version"
|
|
|
|
def __str__(self):
|
|
return self.version
|