HH/apps/complaints/ui_views_explanation.py
ismail c5f76b3855
Some checks are pending
Build and Push Docker Image / build (push) Waiting to run
updates
2026-05-11 14:45:30 +03:00

214 lines
8.4 KiB
Python

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.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 send_to_department_form(request, pk):
complaint = get_object_or_404(
Complaint.objects.prefetch_related(
"involved_staff__staff__department",
"involved_staff__staff__report_to",
"involved_departments__department__respondent",
"involved_departments__department__manager",
),
pk=pk,
)
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."))
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)
involved_staff = complaint.involved_staff.select_related(
"staff", "staff__department", "staff__report_to"
).all()
department_groups = {}
ungrouped_staff = []
# Build department groups from involved_departments first
involved_departments = complaint.involved_departments.select_related(
"department__respondent", "department__manager"
).all()
for dept_inv in involved_departments:
dept = dept_inv.department
if not dept or not dept.respondent:
continue
dept_key = str(dept.id)
if dept_key not in department_groups:
champion = dept.respondent
champion_email = champion.email or (champion.user.email if champion.user else None)
dept_manager = dept.manager
department_groups[dept_key] = {
"department_id": dept_key,
"department_name": dept.get_localized_name(),
"champion": champion,
"champion_id": str(champion.id),
"champion_name": champion.get_full_name(),
"champion_email": champion_email,
"dept_manager": dept_manager,
"dept_manager_id": str(dept_manager.id) if dept_manager else None,
"dept_manager_name": dept_manager.get_full_name() if dept_manager else None,
"dept_manager_email": dept_manager.email if dept_manager else None,
"staff_list": [],
}
# Add involved staff to their department groups
for staff_inv in involved_staff:
staff = staff_inv.staff
dept = staff.department
entry = {
"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),
"role": staff_inv.get_role_display(),
}
if dept and dept.respondent:
dept_key = str(dept.id)
if dept_key in department_groups:
department_groups[dept_key]["staff_list"].append(entry)
else:
# This shouldn't happen if we built department_groups from involved_departments,
# but handle as fallback
champion = dept.respondent
champion_email = champion.email or (champion.user.email if champion.user else None)
dept_manager = dept.manager
department_groups[dept_key] = {
"department_id": dept_key,
"department_name": dept.get_localized_name(),
"champion": champion,
"champion_id": str(champion.id),
"champion_name": champion.get_full_name(),
"champion_email": champion_email,
"dept_manager": dept_manager,
"dept_manager_id": str(dept_manager.id) if dept_manager else None,
"dept_manager_name": dept_manager.get_full_name() if dept_manager else None,
"dept_manager_email": dept_manager.email if dept_manager else None,
"staff_list": [entry],
}
else:
ungrouped_staff.append(entry)
# Only show error if there are NO departments with champions AND no staff
if not department_groups and not involved_staff.exists():
messages.error(request, _("No staff members or departments are involved in this complaint."))
return redirect("complaints:complaint_detail", pk=complaint.pk)
if request.method == "POST":
action = request.POST.get("action", "send")
selected_dept_ids = request.POST.getlist("selected_departments")
request_message = request.POST.get("request_message", "").strip()
if not selected_dept_ids:
messages.error(request, _("Please select at least one department."))
return render(
request,
"complaints/send_to_department_form.html",
{
"complaint": complaint,
"department_groups": department_groups,
"ungrouped_staff": ungrouped_staff,
},
)
if action == "preview":
preview_depts = []
for dept_id in selected_dept_ids:
dept_info = department_groups.get(dept_id)
if dept_info:
preview_depts.append(dept_info)
return render(
request,
"complaints/send_to_department_preview.html",
{
"complaint": complaint,
"preview_depts": preview_depts,
"selected_dept_ids": selected_dept_ids,
"request_message": request_message,
},
)
from django.contrib.sites.shortcuts import get_current_site
site = get_current_site(request)
results = ComplaintService.send_to_department(
complaint,
department_groups,
selected_dept_ids,
request_message,
request.user,
site.domain,
request=request,
)
if results["champion_count"] == 0 and results["manager_count"] == 0:
if results["skipped_no_email"] > 0:
messages.warning(
request,
_(
"No explanation requests were sent. {} department(s) have champions without email addresses."
).format(results["skipped_no_email"]),
)
else:
messages.warning(
request, _("No explanation requests were sent. Please check department champion configuration.")
)
elif results["champion_count"] == 0 and results["manager_count"] > 0:
messages.warning(
request,
_(
"Only department manager notifications were sent ({}). Champion explanation requests could not be sent."
).format(results["manager_count"]),
)
else:
messages.success(
request,
_("Explanation requests sent! Champions: {}, Department managers notified: {}.").format(
results["champion_count"], results["manager_count"]
),
)
return redirect("complaints:complaint_detail", pk=complaint.pk)
return render(
request,
"complaints/send_to_department_form.html",
{
"complaint": complaint,
"department_groups": department_groups,
"ungrouped_staff": ungrouped_staff,
},
)