""" Survey forms for CRUD operations """ from django import forms from django.utils.translation import gettext_lazy as _ from apps.organizations.models import Patient, Staff, Hospital from apps.core.form_mixins import HospitalFieldMixin from .models import SurveyInstance, SurveyTemplate, SurveyQuestion class SurveyTemplateForm(HospitalFieldMixin, forms.ModelForm): """ Form for creating/editing survey templates. Hospital field visibility: - PX Admins: See dropdown with all hospitals - Others: Hidden field, auto-set to user's hospital """ class Meta: model = SurveyTemplate fields = ["name", "name_ar", "hospital", "survey_type", "scoring_method", "negative_threshold", "is_active"] widgets = { "name": forms.TextInput(attrs={"class": "form-control", "placeholder": "e.g., MD Consultation Feedback"}), "name_ar": forms.TextInput(attrs={"class": "form-control", "placeholder": "الاسم بالعربية"}), "hospital": forms.Select(attrs={"class": "form-select"}), "survey_type": forms.Select(attrs={"class": "form-select"}), "scoring_method": forms.Select(attrs={"class": "form-select"}), "negative_threshold": forms.NumberInput( attrs={"class": "form-control", "step": "0.1", "min": "1", "max": "5"} ), "is_active": forms.CheckboxInput(attrs={"class": "form-check-input"}), } class SurveyQuestionForm(forms.ModelForm): """Form for creating/editing survey questions""" class Meta: model = SurveyQuestion fields = ["text", "text_ar", "question_type", "order", "is_required", "choices_json"] widgets = { "text": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Enter question in English"} ), "text_ar": forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "أدخل السؤال بالعربية"} ), "question_type": forms.Select(attrs={"class": "form-select"}), "order": forms.NumberInput(attrs={"class": "form-control", "min": "0"}), "is_required": forms.CheckboxInput(attrs={"class": "form-check-input"}), "choices_json": forms.Textarea( attrs={ "class": "form-control", "rows": 5, "placeholder": '[{"value": "1", "label": "Option 1", "label_ar": "خيار 1"}]', } ), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.fields["choices_json"].required = False self.fields["choices_json"].help_text = _( "JSON array of choices for multiple choice questions. " 'Format: [{"value": "1", "label": "Option 1", "label_ar": "خيار 1"}]' ) SurveyQuestionFormSet = forms.inlineformset_factory( SurveyTemplate, SurveyQuestion, form=SurveyQuestionForm, extra=1, can_delete=True, min_num=1, validate_min=True ) class ManualSurveySendForm(forms.Form): """Form for manually sending surveys to patients or staff""" RECIPIENT_TYPE_CHOICES = [ ("patient", _("Patient")), ("staff", _("Staff")), ] DELIVERY_CHANNEL_CHOICES = [ ("email", _("Email")), ("sms", _("SMS")), ] def __init__(self, request=None, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request self.user = request.user if request else None # Determine hospital context hospital = None if self.user and self.user.is_px_admin(): hospital = getattr(request, "tenant_hospital", None) elif self.user and self.user.hospital: hospital = self.user.hospital # Filter survey templates by hospital if hospital: self.fields["survey_template"].queryset = SurveyTemplate.objects.filter(hospital=hospital, is_active=True) survey_template = forms.ModelChoiceField( queryset=SurveyTemplate.objects.filter(is_active=True), label=_("Survey Template"), widget=forms.Select(attrs={"class": "form-select", "data-placeholder": _("Select a survey template")}), ) recipient_type = forms.ChoiceField( choices=RECIPIENT_TYPE_CHOICES, label=_("Recipient Type"), widget=forms.RadioSelect(attrs={"class": "form-check-input"}), ) recipient = forms.CharField( label=_("Recipient"), widget=forms.TextInput( attrs={ "class": "form-control", "placeholder": _("Search by name or ID..."), "data-search-url": "/api/recipients/search/", } ), help_text=_("Start typing to search for patient or staff"), ) delivery_channel = forms.ChoiceField( choices=DELIVERY_CHANNEL_CHOICES, label=_("Delivery Channel"), widget=forms.Select(attrs={"class": "form-select"}), ) custom_message = forms.CharField( label=_("Custom Message (Optional)"), required=False, widget=forms.Textarea( attrs={ "class": "form-control", "rows": 3, "placeholder": _("Add a custom message to the survey invitation..."), } ), ) class ManualPhoneSurveySendForm(forms.Form): """Form for sending surveys to a manually entered phone number""" def __init__(self, request=None, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request self.user = request.user if request else None # Determine hospital context hospital = None if self.user and self.user.is_px_admin(): hospital = getattr(request, "tenant_hospital", None) elif self.user and self.user.hospital: hospital = self.user.hospital # Filter survey templates by hospital if hospital: self.fields["survey_template"].queryset = SurveyTemplate.objects.filter(hospital=hospital, is_active=True) survey_template = forms.ModelChoiceField( queryset=SurveyTemplate.objects.filter(is_active=True), label=_("Survey Template"), widget=forms.Select(attrs={"class": "form-select"}), ) phone_number = forms.CharField( label=_("Phone Number"), widget=forms.TextInput(attrs={"class": "form-control", "placeholder": _("+966501234567")}), help_text=_("Enter phone number with country code (e.g., +966...)"), ) recipient_name = forms.CharField( label=_("Recipient Name (Optional)"), required=False, widget=forms.TextInput(attrs={"class": "form-control", "placeholder": _("Patient Name")}), ) custom_message = forms.CharField( label=_("Custom Message (Optional)"), required=False, widget=forms.Textarea( attrs={ "class": "form-control", "rows": 3, "placeholder": _("Add a custom message to the survey invitation..."), } ), ) def clean_phone_number(self): phone = self.cleaned_data["phone_number"].strip() # Remove spaces, dashes, parentheses phone = phone.replace(" ", "").replace("-", "").replace("(", "").replace(")", "") if not phone.startswith("+"): raise forms.ValidationError(_("Phone number must start with country code (e.g., +966)")) return phone class BulkCSVSurveySendForm(forms.Form): """Form for bulk sending surveys via CSV upload""" survey_template = forms.ModelChoiceField( queryset=SurveyTemplate.objects.filter(is_active=True), label=_("Survey Template"), widget=forms.Select(attrs={"class": "form-select"}), ) csv_file = forms.FileField( label=_("CSV File"), widget=forms.FileInput(attrs={"class": "form-control", "accept": ".csv"}), help_text=_("Upload CSV with phone numbers. Format: phone_number,name(optional)"), ) custom_message = forms.CharField( label=_("Custom Message (Optional)"), required=False, widget=forms.Textarea( attrs={ "class": "form-control", "rows": 3, "placeholder": _("Add a custom message to the survey invitation..."), } ), ) def __init__(self, request=None, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request self.user = request.user if request else None # Determine hospital context hospital = None if self.user and self.user.is_px_admin(): hospital = getattr(request, "tenant_hospital", None) elif self.user and self.user.hospital: hospital = self.user.hospital # Filter survey templates by hospital if hospital: self.fields["survey_template"].queryset = SurveyTemplate.objects.filter(hospital=hospital, is_active=True) class HISPatientImportForm(HospitalFieldMixin, forms.Form): """ Form for importing patient data from HIS/MOH Statistics CSV. Hospital field visibility: - PX Admins: See dropdown with all hospitals - Others: Hidden field, auto-set to user's hospital """ hospital = forms.ModelChoiceField( queryset=Hospital.objects.filter(status="active"), label=_("Hospital"), widget=forms.Select(attrs={"class": "form-select"}), help_text=_("Select the hospital for these patient records"), ) csv_file = forms.FileField( label=_("HIS Statistics CSV File"), widget=forms.FileInput(attrs={"class": "form-control", "accept": ".csv"}), help_text=_("Upload MOH Statistics CSV with patient visit data"), ) skip_header_rows = forms.IntegerField( label=_("Skip Header Rows"), initial=5, min_value=0, max_value=10, widget=forms.NumberInput(attrs={"class": "form-control"}), help_text=_("Number of metadata/header rows to skip before data rows"), ) class HISSurveySendForm(forms.Form): """Form for sending surveys to imported HIS patients""" survey_template = forms.ModelChoiceField( queryset=SurveyTemplate.objects.filter(is_active=True), label=_("Survey Template"), widget=forms.Select(attrs={"class": "form-select"}), ) delivery_channel = forms.ChoiceField( choices=[ ("sms", _("SMS")), ("email", _("Email")), ("both", _("Both SMS and Email")), ], label=_("Delivery Channel"), initial="sms", widget=forms.Select(attrs={"class": "form-select"}), ) custom_message = forms.CharField( label=_("Custom Message (Optional)"), required=False, widget=forms.Textarea( attrs={ "class": "form-control", "rows": 3, "placeholder": _("Add a custom message to the survey invitation..."), } ), ) patient_ids = forms.CharField(widget=forms.HiddenInput(), required=True) def __init__(self, request=None, *args, **kwargs): super().__init__(*args, **kwargs) self.request = request self.user = request.user if request else None # Determine hospital context hospital = None if self.user and self.user.is_px_admin(): hospital = getattr(request, "tenant_hospital", None) elif self.user and self.user.hospital: hospital = self.user.hospital # Filter survey templates by hospital if hospital: self.fields["survey_template"].queryset = SurveyTemplate.objects.filter(hospital=hospital, is_active=True)