""" 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 generate random password"), }), ) 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) 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): import secrets import string user = super().save(commit=False) password = self.cleaned_data.get("password") if not password: alphabet = string.ascii_letters + string.digits + "!@#$%^&*" password = ''.join(secrets.choice(alphabet) for _ in range(16)) self._generated_password = password user.set_password(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