""" RCA (Root Cause Analysis) forms """ from django import forms from django.utils import timezone from apps.core.models import PriorityChoices from .models import ( RCAActionStatus, RCAActionType, RCACorrectiveAction, RCAStatus, RCASeverity, RCAAttachment, RCANote, RCARootCause, RootCauseAnalysis, ) class RootCauseAnalysisForm(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): user = kwargs.pop('user', None) 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') # Set initial hospital if user has one if user and not self.instance.pk: from apps.organizations.models import Hospital try: user_hospital = Hospital.objects.filter( staff__user=user ).first() if user_hospital: self.fields['hospital'].initial = user_hospital self.fields['hospital'].widget.attrs['readonly'] = True except: pass 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' }), }