""" Explanation request UI views for complaints. """ from django.contrib import messages from django.contrib.auth.decorators import login_required from django.http import HttpResponseForbidden from django.shortcuts import get_object_or_404, redirect, render from django.utils import timezone from django.utils.translation import gettext as _ from django.views.decorators.http import require_http_methods from apps.core.services import AuditService from apps.notifications.services import NotificationService from apps.organizations.models import Staff from .models import Complaint, ComplaintExplanation, ComplaintStatus from .services.complaint_service import ComplaintService, ComplaintServiceError @login_required @require_http_methods(["GET", "POST"]) def request_explanation_form(request, pk): """ Form to request explanations from involved staff members. Shows all involved staff with their managers and departments. All staff and managers are selected by default. """ complaint = get_object_or_404( Complaint.objects.prefetch_related( "involved_staff__staff__department", "involved_staff__staff__report_to", ), pk=pk, ) # Check permissions user = request.user can_request = ( user.is_px_admin() or user.is_hospital_admin() or (user.is_department_manager() and complaint.department == user.department) or (complaint.hospital == user.hospital) ) if not can_request: return HttpResponseForbidden(_("You don't have permission to request explanations.")) # Check complaint is in active status if not complaint.is_active_status: messages.error( request, _( "Cannot request explanation for complaint with status '{}'. Complaint must be Open, In Progress, or Partially Resolved." ).format(complaint.get_status_display()), ) return redirect("complaints:complaint_detail", pk=complaint.pk) # Get all involved staff with their managers involved_staff = complaint.involved_staff.select_related("staff", "staff__department", "staff__report_to").all() if not involved_staff.exists(): messages.error(request, _("No staff members are involved in this complaint.")) return redirect("complaints:complaint_detail", pk=complaint.pk) # Build list of recipients (staff + managers) recipients = [] manager_ids = set() for staff_inv in involved_staff: staff = staff_inv.staff manager = staff.report_to recipient = { "staff_inv": staff_inv, "staff": staff, "staff_id": str(staff.id), "staff_name": staff.get_full_name(), "staff_email": staff.email or (staff.user.email if staff.user else None), "department": staff.department.name if staff.department else "-", "role": staff_inv.get_role_display(), "manager": manager, "manager_id": str(manager.id) if manager else None, "manager_name": manager.get_full_name() if manager else None, "manager_email": manager.email if manager else None, } recipients.append(recipient) # Track unique managers if manager and manager.id not in manager_ids: manager_ids.add(manager.id) if request.method == "POST": # Get selected staff and managers selected_staff_ids = request.POST.getlist("selected_staff") selected_manager_ids = request.POST.getlist("selected_managers") request_message = request.POST.get("request_message", "").strip() if not selected_staff_ids: messages.error(request, _("Please select at least one staff member.")) return render( request, "complaints/request_explanation_form.html", { "complaint": complaint, "recipients": recipients, "manager_ids": manager_ids, }, ) # Send explanation requests from django.contrib.sites.shortcuts import get_current_site site = get_current_site(request) results = ComplaintService.request_explanation( complaint, recipients, selected_staff_ids, selected_manager_ids, request_message, request.user, site.domain, request=request, ) # Check results and show appropriate message if results["staff_count"] == 0 and results["manager_count"] == 0: if results["skipped_no_email"] > 0: messages.warning( request, _( "No explanation requests were sent. {} staff member(s) do not have email addresses. Please update staff records with email addresses before sending explanation requests." ).format(results["skipped_no_email"]), ) else: messages.warning( request, _("No explanation requests were sent. Please check staff email configuration.") ) elif results["staff_count"] == 0 and results["manager_count"] > 0: messages.warning( request, _( "Only manager notifications were sent ({}). Staff explanation requests could not be sent due to missing email addresses." ).format(results["manager_count"]), ) else: messages.success( request, _("Explanation requests sent successfully! Staff: {}, Managers notified: {}.").format( results["staff_count"], results["manager_count"] ), ) return redirect("complaints:complaint_detail", pk=complaint.pk) return render( request, "complaints/request_explanation_form.html", { "complaint": complaint, "recipients": recipients, "manager_ids": manager_ids, }, )