HH/apps/complaints/ui_views_explanation.py
2026-03-28 14:03:56 +03:00

165 lines
6.0 KiB
Python

"""
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,
},
)