nexus-5/core/models/profile.py
2026-01-26 11:09:40 -05:00

70 lines
2.6 KiB
Python

from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.db import models
from django_choices_field.fields import TextChoicesField
from core.models import Customer
from core.models.base import Contact
from core.models.enums import StatusChoices, RoleChoices
class Profile(Contact):
"""Base profile class with common functionality"""
user = models.OneToOneField(
User, on_delete=models.SET_NULL, related_name='%(class)s',
null=True, blank=True,
help_text="Optional Django user for admin access only"
)
status = TextChoicesField(choices_enum=StatusChoices, default=StatusChoices.ACTIVE,
help_text="Current status of the profile")
notes = models.TextField(blank=True, default="", verbose_name="Notes")
ory_kratos_id = models.CharField(
max_length=255, unique=True, null=True, blank=True,
verbose_name="Ory Kratos Identity ID",
help_text="Unique identifier from Ory Kratos authentication system"
)
email = models.EmailField(null=True, blank=True)
class Meta:
abstract = True
ordering = ['last_name', 'first_name']
def save(self, *args, **kwargs):
# Validate new users against existing profiles (if user is set)
# Strict enforcement of one profile per user
if not self.pk and self.user:
profile_types = [CustomerProfile, TeamProfile]
current_type = type(self)
for profile_type in profile_types:
if profile_type != current_type:
if profile_type.objects.filter(user=self.user).exists():
raise ValidationError(
f"User already has a {profile_type.__name__}. "
f"Cannot create {current_type.__name__}."
)
super().save(*args, **kwargs)
class CustomerProfile(Profile):
"""External/public-facing customer accounts"""
customers = models.ManyToManyField(
Customer,
related_name='profiles',
blank=True,
help_text="Customers this profile has access to"
)
class Meta:
verbose_name = "Customer Profile"
verbose_name_plural = "Customer Profiles"
class TeamProfile(Profile):
"""Internal team member accounts"""
role = TextChoicesField(choices_enum=RoleChoices, default=RoleChoices.TEAM_MEMBER,
help_text="Role of the team member")
class Meta:
verbose_name = "Team Profile"
verbose_name_plural = "Team Profiles"