141 lines
5.0 KiB
Python
141 lines
5.0 KiB
Python
"""
|
|
PX Action Center forms - Manual action creation and management
|
|
"""
|
|
|
|
from django import forms
|
|
from django.db.models import Q
|
|
|
|
from apps.core.models import PriorityChoices, SeverityChoices
|
|
|
|
from .models import PXAction, ActionSource, ActionStatus
|
|
|
|
|
|
class ManualActionForm(forms.ModelForm):
|
|
"""
|
|
Form for manually creating PX Actions.
|
|
|
|
Features:
|
|
- Source type selection including meeting types
|
|
- User permission-based filtering
|
|
- Cascading dropdowns (hospital → department)
|
|
- Assignment to users
|
|
"""
|
|
|
|
class Meta:
|
|
model = PXAction
|
|
fields = [
|
|
"source_type",
|
|
"title",
|
|
"description",
|
|
"hospital",
|
|
"department",
|
|
"category",
|
|
"priority",
|
|
"severity",
|
|
"assigned_to",
|
|
"due_at",
|
|
"requires_approval",
|
|
"action_plan",
|
|
]
|
|
widgets = {
|
|
"title": forms.TextInput(attrs={"class": "form-control", "placeholder": "Brief title for the action plan"}),
|
|
"description": forms.Textarea(
|
|
attrs={
|
|
"class": "form-control",
|
|
"rows": 4,
|
|
"placeholder": "Detailed description of the issue or improvement needed",
|
|
}
|
|
),
|
|
"due_at": forms.DateTimeInput(attrs={"type": "datetime-local", "class": "form-control"}),
|
|
"action_plan": forms.Textarea(
|
|
attrs={"class": "form-control", "rows": 4, "placeholder": "Proposed action steps to address the issue"}
|
|
),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
request = kwargs.pop("request", None)
|
|
user = request.user if request else None
|
|
tenant_hospital = getattr(request, "tenant_hospital", None) if request else None
|
|
super().__init__(*args, **kwargs)
|
|
|
|
# Make hospital field hidden and auto-set based on user context
|
|
self.fields["hospital"].widget = forms.HiddenInput()
|
|
self.fields["hospital"].required = False
|
|
|
|
# Set hospital value based on user context
|
|
if user:
|
|
if user.is_px_admin() and tenant_hospital:
|
|
self.fields["hospital"].initial = tenant_hospital
|
|
self.fields["hospital"].queryset = self.fields["hospital"].queryset.filter(id=tenant_hospital.id)
|
|
hospital = tenant_hospital
|
|
elif user.hospital:
|
|
self.fields["hospital"].initial = user.hospital
|
|
self.fields["hospital"].queryset = self.fields["hospital"].queryset.filter(id=user.hospital.id)
|
|
hospital = user.hospital
|
|
else:
|
|
hospital = None
|
|
self.fields["hospital"].queryset = self.fields["hospital"].queryset.none()
|
|
else:
|
|
hospital = None
|
|
|
|
# Make source type required
|
|
self.fields["source_type"].required = True
|
|
self.fields["source_type"].widget.attrs["class"] = "form-select"
|
|
|
|
# Make category required
|
|
self.fields["category"].required = True
|
|
self.fields["category"].widget.attrs["class"] = "form-select"
|
|
|
|
# Make priority and severity required
|
|
self.fields["priority"].required = True
|
|
self.fields["priority"].widget.attrs["class"] = "form-select"
|
|
self.fields["severity"].required = True
|
|
self.fields["severity"].widget.attrs["class"] = "form-select"
|
|
|
|
# Filter departments based on hospital
|
|
if hospital:
|
|
self.fields["department"].queryset = self.fields["department"].queryset.filter(hospital=hospital)
|
|
self.fields["department"].widget.attrs["class"] = "form-select"
|
|
|
|
# Filter assignable users
|
|
from apps.accounts.models import User
|
|
|
|
if hospital:
|
|
self.fields["assigned_to"].queryset = User.objects.filter(is_active=True, hospital=hospital).order_by(
|
|
"first_name", "last_name"
|
|
)
|
|
self.fields["assigned_to"].widget.attrs["class"] = "form-select"
|
|
else:
|
|
self.fields["assigned_to"].queryset = User.objects.none()
|
|
|
|
# Set default for requires_approval
|
|
self.fields["requires_approval"].initial = True
|
|
self.fields["requires_approval"].widget.attrs["class"] = "form-check-input"
|
|
|
|
def clean_hospital(self):
|
|
"""Validate hospital field"""
|
|
hospital = self.cleaned_data.get("hospital")
|
|
if not hospital:
|
|
raise forms.ValidationError("Hospital is required.")
|
|
return hospital
|
|
|
|
def clean_due_at(self):
|
|
"""Validate due date is in the future"""
|
|
due_at = self.cleaned_data.get("due_at")
|
|
if due_at:
|
|
from django.utils import timezone
|
|
|
|
if due_at <= timezone.now():
|
|
raise forms.ValidationError("Due date must be in the future.")
|
|
return due_at
|
|
|
|
def save(self, commit=True):
|
|
"""Save action with manual source type"""
|
|
action = super().save(commit=False)
|
|
action.source_type = ActionSource.MANUAL
|
|
|
|
if commit:
|
|
action.save()
|
|
|
|
return action
|