HH/apps/accounts/forms.py
2026-07-12 11:18:20 +03:00

237 lines
9.6 KiB
Python

"""
Accounts forms - User create/edit for config console
"""
from django import forms
from django.contrib.auth.models import Group
from django.utils.translation import gettext_lazy as _
from apps.accounts.models import User
from apps.organizations.models import Hospital, Department
from apps.core.form_mixins import DepartmentFieldMixin
class UserCreateForm(DepartmentFieldMixin, forms.ModelForm):
"""Form for creating a new user in the config console"""
email = forms.EmailField(
label=_("Email"),
widget=forms.EmailInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
"placeholder": "user@example.com",
}),
)
first_name = forms.CharField(
label=_("First Name"),
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
last_name = forms.CharField(
label=_("Last Name"),
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
phone = forms.CharField(
label=_("Phone"),
required=False,
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
"placeholder": "+966501234567",
}),
)
employee_id = forms.CharField(
label=_("Employee ID"),
required=False,
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
hospital = forms.ModelChoiceField(
queryset=Hospital.objects.filter(status="active"),
label=_("Hospital"),
required=False,
widget=forms.Select(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
department = forms.ModelChoiceField(
queryset=Department.objects.none(),
label=_("Department"),
required=False,
widget=forms.Select(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
groups = forms.ModelMultipleChoiceField(
queryset=Group.objects.all(),
label=_("Roles"),
required=False,
widget=forms.CheckboxSelectMultiple(attrs={
"class": "role-checkbox",
}),
)
password = forms.CharField(
label=_("Password"),
required=False,
widget=forms.PasswordInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
"placeholder": _("Leave blank to send a password setup link via email"),
}),
)
password_confirm = forms.CharField(
label=_("Confirm Password"),
required=False,
widget=forms.PasswordInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
is_active = forms.BooleanField(
label=_("Active"),
initial=True,
required=False,
widget=forms.CheckboxInput(attrs={
"class": "w-5 h-5 text-navy border-slate-300 rounded focus:ring-navy",
}),
)
class Meta:
model = User
fields = [
"email", "first_name", "last_name", "phone", "employee_id",
"hospital", "department", "groups", "is_active",
]
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
self.user = kwargs.pop("user", None) or (self.request.user if self.request else None)
super().__init__(*args, **kwargs)
self.fields["groups"].queryset = Group.objects.all().order_by("name")
if self.user and self.user.is_hospital_admin() and self.user.hospital:
self.fields["hospital"].initial = self.user.hospital
self.fields["hospital"].queryset = Hospital.objects.filter(id=self.user.hospital.id)
elif self.user and self.user.is_px_admin() and getattr(self.request, "tenant_hospital", None):
self.fields["hospital"].initial = self.request.tenant_hospital
def clean_email(self):
email = self.cleaned_data.get("email")
if User.objects.filter(email=email).exists():
raise forms.ValidationError(_("A user with this email already exists."))
return email
def clean(self):
cleaned_data = super().clean()
password = cleaned_data.get("password")
password_confirm = cleaned_data.get("password_confirm")
if password and password_confirm and password != password_confirm:
self.add_error("password_confirm", _("Passwords do not match."))
return cleaned_data
def save(self, commit=True):
user = super().save(commit=False)
password = self.cleaned_data.get("password")
if password:
user.set_password(password)
else:
user.set_unusable_password()
if commit:
user.save()
selected_groups = self.cleaned_data.get("groups")
if selected_groups:
user.groups.set(selected_groups)
return user
class UserEditForm(DepartmentFieldMixin, forms.ModelForm):
"""Form for editing an existing user in the config console"""
first_name = forms.CharField(
label=_("First Name"),
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
last_name = forms.CharField(
label=_("Last Name"),
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
phone = forms.CharField(
label=_("Phone"),
required=False,
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
"placeholder": "+966501234567",
}),
)
employee_id = forms.CharField(
label=_("Employee ID"),
required=False,
widget=forms.TextInput(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
hospital = forms.ModelChoiceField(
queryset=Hospital.objects.filter(status="active"),
label=_("Hospital"),
required=False,
widget=forms.Select(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
department = forms.ModelChoiceField(
queryset=Department.objects.none(),
label=_("Department"),
required=False,
widget=forms.Select(attrs={
"class": "w-full px-4 py-3 border border-slate-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-navy focus:border-transparent transition bg-white text-sm",
}),
)
groups = forms.ModelMultipleChoiceField(
queryset=Group.objects.all(),
label=_("Roles"),
required=False,
widget=forms.CheckboxSelectMultiple(attrs={
"class": "role-checkbox",
}),
)
is_active = forms.BooleanField(
label=_("Active"),
initial=True,
required=False,
widget=forms.CheckboxInput(attrs={
"class": "w-5 h-5 text-navy border-slate-300 rounded focus:ring-navy",
}),
)
class Meta:
model = User
fields = [
"first_name", "last_name", "phone", "employee_id",
"hospital", "department", "groups", "is_active",
]
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("request", None)
self.user = kwargs.pop("user", None) or (self.request.user if self.request else None)
super().__init__(*args, **kwargs)
self.fields["groups"].queryset = Group.objects.all().order_by("name")
if self.instance and self.instance.pk:
self.fields["groups"].initial = self.instance.groups.all()
if self.instance.hospital:
self.fields["hospital"].initial = self.instance.hospital
self.fields["hospital"].queryset = Hospital.objects.filter(id=self.instance.hospital.id)
def save(self, commit=True):
user = super().save(commit=False)
if commit:
user.save()
selected_groups = self.cleaned_data.get("groups")
if selected_groups is not None:
user.groups.set(selected_groups)
return user