""" RCA (Root Cause Analysis) forms """ from django import forms from django.utils import timezone from apps.core.models import PriorityChoices from apps.core.form_mixins import HospitalFieldMixin from .models import ( RCAActionStatus, RCAActionType, RCACorrectiveAction, RCAStatus, RCASeverity, RCAAttachment, RCANote, RCARootCause, RootCauseAnalysis, ) class RootCauseAnalysisForm(HospitalFieldMixin, forms.ModelForm): """Form for creating and editing RootCauseAnalysis""" class Meta: model = RootCauseAnalysis fields = [ "title", "description", "background", "hospital", "department", "status", "severity", "priority", "assigned_to", "target_completion_date", "root_cause_summary", ] widgets = { "title": forms.TextInput(attrs={"class": "form-control", "placeholder": "Enter RCA title"}), "description": forms.Textarea( attrs={"class": "form-control", "rows": 4, "placeholder": "Describe the incident or issue"} ), "background": forms.Textarea( attrs={"class": "form-control", "rows": 3, "placeholder": "Provide background information and context"} ), "hospital": forms.Select(attrs={"class": "form-select"}), "department": forms.Select(attrs={"class": "form-select"}), "status": forms.Select(attrs={"class": "form-select"}), "severity": forms.Select(attrs={"class": "form-select"}), "priority": forms.Select(attrs={"class": "form-select"}), "assigned_to": forms.Select(attrs={"class": "form-select"}), "target_completion_date": forms.DateInput(attrs={"class": "form-control", "type": "date"}), "root_cause_summary": forms.Textarea( attrs={"class": "form-control", "rows": 4, "placeholder": "Summary of root cause analysis findings"} ), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Filter assigned_to to show only active users if "assigned_to" in self.fields: from apps.accounts.models import User self.fields["assigned_to"].queryset = User.objects.filter(is_active=True).order_by("email") class RCARootCauseForm(forms.ModelForm): """Form for creating and editing RCARootCause""" class Meta: model = RCARootCause fields = [ "description", "category", "contributing_factors", "likelihood", "impact", "evidence", ] widgets = { "description": forms.Textarea( attrs={"class": "form-control", "rows": 3, "placeholder": "Describe the root cause"} ), "category": forms.Select(attrs={"class": "form-select"}), "contributing_factors": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Factors that contributed to this root cause"} ), "likelihood": forms.NumberInput(attrs={"class": "form-control", "min": 1, "max": 5, "placeholder": "1-5"}), "impact": forms.NumberInput(attrs={"class": "form-control", "min": 1, "max": 5, "placeholder": "1-5"}), "evidence": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Evidence supporting this root cause"} ), } def clean_likelihood(self): likelihood = self.cleaned_data.get("likelihood") if likelihood and (likelihood < 1 or likelihood > 5): raise forms.ValidationError("Likelihood must be between 1 and 5") return likelihood def clean_impact(self): impact = self.cleaned_data.get("impact") if impact and (impact < 1 or impact > 5): raise forms.ValidationError("Impact must be between 1 and 5") return impact class RCACorrectiveActionForm(forms.ModelForm): """Form for creating and editing RCACorrectiveAction""" class Meta: model = RCACorrectiveAction fields = [ "description", "action_type", "root_cause", "responsible_person", "target_date", "completion_date", "status", "effectiveness_measure", "effectiveness_assessment", "effectiveness_score", "obstacles", ] widgets = { "description": forms.Textarea( attrs={"class": "form-control", "rows": 3, "placeholder": "Describe the corrective action"} ), "action_type": forms.Select(attrs={"class": "form-select"}), "root_cause": forms.Select(attrs={"class": "form-select"}), "responsible_person": forms.Select(attrs={"class": "form-select"}), "target_date": forms.DateInput(attrs={"class": "form-control", "type": "date"}), "completion_date": forms.DateInput(attrs={"class": "form-control", "type": "date"}), "status": forms.Select(attrs={"class": "form-select"}), "effectiveness_measure": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "How will effectiveness be measured?"} ), "effectiveness_assessment": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Assessment of action effectiveness"} ), "effectiveness_score": forms.NumberInput( attrs={"class": "form-control", "min": 1, "max": 5, "placeholder": "1-5"} ), "obstacles": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Obstacles encountered during implementation"} ), } def __init__(self, *args, **kwargs): rca = kwargs.pop("rca", None) super().__init__(*args, **kwargs) # Filter root_cause to show only for this RCA if "root_cause" in self.fields and rca: self.fields["root_cause"].queryset = rca.root_causes.all() def clean_effectiveness_score(self): score = self.cleaned_data.get("effectiveness_score") if score and (score < 1 or score > 5): raise forms.ValidationError("Effectiveness score must be between 1 and 5") return score class RCAFilterForm(forms.Form): """Form for filtering RCA list""" status = forms.ChoiceField( required=False, choices=[("", "All Statuses")] + list(RCAStatus.choices), widget=forms.Select(attrs={"class": "form-select"}), ) severity = forms.ChoiceField( required=False, choices=[("", "All Severities")] + list(RCASeverity.choices), widget=forms.Select(attrs={"class": "form-select"}), ) priority = forms.ChoiceField( required=False, choices=[("", "All Priorities")] + list(PriorityChoices.choices), widget=forms.Select(attrs={"class": "form-select"}), ) hospital = forms.ChoiceField( required=False, choices=[("", "All Hospitals")], widget=forms.Select(attrs={"class": "form-select"}) ) department = forms.ChoiceField( required=False, choices=[("", "All Departments")], widget=forms.Select(attrs={"class": "form-select"}) ) search = forms.CharField( required=False, widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "Search RCAs..."}) ) date_from = forms.DateField(required=False, widget=forms.DateInput(attrs={"class": "form-control", "type": "date"})) date_to = forms.DateField(required=False, widget=forms.DateInput(attrs={"class": "form-control", "type": "date"})) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Populate hospital choices from apps.organizations.models import Hospital hospital_choices = [("", "All Hospitals")] hospital_choices.extend([(h.id, h.name) for h in Hospital.objects.all()]) self.fields["hospital"].choices = hospital_choices class RCAStatusChangeForm(forms.Form): """Form for changing RCA status""" new_status = forms.ChoiceField(choices=RCAStatus.choices, widget=forms.Select(attrs={"class": "form-select"})) notes = forms.CharField( required=False, widget=forms.Textarea( attrs={"class": "form-control", "rows": 3, "placeholder": "Add notes about this status change"} ), ) class RCAApprovalForm(forms.Form): """Form for approving RCA""" approval_notes = forms.CharField( required=False, widget=forms.Textarea(attrs={"class": "form-control", "rows": 3, "placeholder": "Add approval notes"}), ) class RCAClosureForm(forms.Form): """Form for closing RCA""" closure_notes = forms.CharField( required=True, widget=forms.Textarea( attrs={"class": "form-control", "rows": 3, "placeholder": "Provide closure notes and summary"} ), ) actual_completion_date = forms.DateField( required=True, widget=forms.DateInput(attrs={"class": "form-control", "type": "date"}) ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Set default to today self.fields["actual_completion_date"].initial = timezone.now().date() class RCAAttachmentForm(forms.ModelForm): """Form for uploading RCA attachments""" class Meta: model = RCAAttachment fields = ["file", "description"] widgets = { "file": forms.FileInput(attrs={"class": "form-control"}), "description": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Describe this attachment"} ), } class RCANoteForm(forms.ModelForm): """Form for adding RCA notes""" class Meta: model = RCANote fields = ["note", "is_internal"] widgets = { "note": forms.Textarea(attrs={"class": "form-control", "rows": 3, "placeholder": "Add a note"}), "is_internal": forms.CheckboxInput(attrs={"class": "form-check-input"}), }