from django.contrib.auth.decorators import login_required from django.core.paginator import Paginator from django.db.models import Q from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from .models import Department, Hospital, Organization, Patient, Staff, StaffSection, StaffSubsection from .forms import StaffForm @login_required def hospital_list(request): """Hospitals list view""" queryset = Hospital.objects.all() # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital: queryset = queryset.filter(id=user.hospital.id) # Apply filters status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(name__icontains=search_query) | Q(name_ar__icontains=search_query) | Q(code__icontains=search_query) ) # Ordering queryset = queryset.order_by('name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) context = { 'page_obj': page_obj, 'hospitals': page_obj.object_list, 'filters': request.GET, } return render(request, 'organizations/hospital_list.html', context) @login_required def department_list(request): """Departments list view""" queryset = Department.objects.select_related('hospital', 'manager') # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital: queryset = queryset.filter(hospital=user.hospital) # Apply filters hospital_filter = request.GET.get('hospital') if hospital_filter: queryset = queryset.filter(hospital_id=hospital_filter) status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(name__icontains=search_query) | Q(name_ar__icontains=search_query) | Q(code__icontains=search_query) ) # Ordering queryset = queryset.order_by('hospital', 'name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get hospitals for filter hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) context = { 'page_obj': page_obj, 'departments': page_obj.object_list, 'hospitals': hospitals, 'filters': request.GET, } return render(request, 'organizations/department_list.html', context) @login_required def staff_list(request): """Staff list view - filtered by tenant hospital""" queryset = Staff.objects.select_related('hospital', 'department', 'user') # Always filter by tenant_hospital (set by TenantMiddleware) # This handles both PX admins (with selected hospital) and regular users if request.tenant_hospital: queryset = queryset.filter(hospital=request.tenant_hospital) # Apply filters department_filter = request.GET.get('department') if department_filter: queryset = queryset.filter(department_id=department_filter) status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) staff_type_filter = request.GET.get('staff_type') if staff_type_filter: queryset = queryset.filter(staff_type=staff_type_filter) # is_head filter is_head_filter = request.GET.get('is_head') if is_head_filter: if is_head_filter.lower() == 'true': queryset = queryset.filter(is_head=True) elif is_head_filter.lower() == 'false': queryset = queryset.filter(is_head=False) # Filter by department ForeignKey department_filter = request.GET.get('department') if department_filter: queryset = queryset.filter(department_id=department_filter) section_filter = request.GET.get('section') if section_filter: queryset = queryset.filter(section__icontains=section_filter) subsection_filter = request.GET.get('subsection') if subsection_filter: queryset = queryset.filter(subsection__icontains=subsection_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query) | Q(employee_id__icontains=search_query) | Q(license_number__icontains=search_query) | Q(specialization__icontains=search_query) | Q(job_title__icontains=search_query) ) # Ordering queryset = queryset.order_by('last_name', 'first_name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get departments for filter dropdown (from current hospital context) if request.tenant_hospital: departments = Department.objects.filter(hospital=request.tenant_hospital, status='active').order_by('name') else: departments = Department.objects.filter(status='active').order_by('name') # Get unique values for section/subsection filters base_queryset = Staff.objects.select_related('hospital', 'department', 'user') if request.tenant_hospital: base_queryset = base_queryset.filter(hospital=request.tenant_hospital) sections = base_queryset.exclude(section='').values_list('section', flat=True).distinct().order_by('section') subsections = base_queryset.exclude(subsection='').values_list('subsection', flat=True).distinct().order_by('subsection') context = { 'staff': page_obj, 'filters': request.GET, 'departments': departments, 'sections': sections, 'subsections': subsections, } return render(request, 'organizations/staff_list.html', context) @login_required def organization_list(request): """Organizations list view""" queryset = Organization.objects.all() # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital and user.hospital.organization: queryset = queryset.filter(id=user.hospital.organization.id) # Apply filters status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) city_filter = request.GET.get('city') if city_filter: queryset = queryset.filter(city__icontains=city_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(name__icontains=search_query) | Q(name_ar__icontains=search_query) | Q(code__icontains=search_query) | Q(license_number__icontains=search_query) ) # Ordering queryset = queryset.order_by('name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) context = { 'page_obj': page_obj, 'organizations': page_obj.object_list, 'filters': request.GET, } return render(request, 'organizations/organization_list.html', context) @login_required def organization_detail(request, pk): """Organization detail view""" organization = Organization.objects.get(pk=pk) # Apply RBAC filters user = request.user if not user.is_px_admin(): if user.hospital and user.hospital.organization: if organization.id != user.hospital.organization.id: # User doesn't have access to this organization from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to view this organization") else: from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to view this organization") hospitals = organization.hospitals.all() context = { 'organization': organization, 'hospitals': hospitals, } return render(request, 'organizations/organization_detail.html', context) @login_required def organization_create(request): """Create organization view""" # Only PX Admins can create organizations user = request.user if not user.is_px_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("Only PX Admins can create organizations") if request.method == 'POST': name = request.POST.get('name') name_ar = request.POST.get('name_ar') code = request.POST.get('code') address = request.POST.get('address', '') city = request.POST.get('city', '') phone = request.POST.get('phone', '') email = request.POST.get('email', '') website = request.POST.get('website', '') license_number = request.POST.get('license_number', '') status = request.POST.get('status', 'active') if name and code: organization = Organization.objects.create( name=name, name_ar=name_ar or name, code=code, address=address, city=city, phone=phone, email=email, website=website, license_number=license_number, status=status ) # Redirect to organization detail from django.shortcuts import redirect return redirect('organizations:organization_detail', pk=organization.id) return render(request, 'organizations/organization_form.html') @login_required def patient_list(request): """Patients list view""" queryset = Patient.objects.select_related('primary_hospital') # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital: queryset = queryset.filter(primary_hospital=user.hospital) # Apply filters hospital_filter = request.GET.get('hospital') if hospital_filter: queryset = queryset.filter(primary_hospital_id=hospital_filter) status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(mrn__icontains=search_query) | Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query) | Q(national_id__icontains=search_query) | Q(phone__icontains=search_query) ) # Ordering queryset = queryset.order_by('last_name', 'first_name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get hospitals for filter hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) context = { 'page_obj': page_obj, 'patients': page_obj.object_list, 'hospitals': hospitals, 'filters': request.GET, } return render(request, 'organizations/patient_list.html', context) @login_required def staff_detail(request, pk): """Staff detail view""" staff = get_object_or_404(Staff.objects.select_related('user', 'hospital', 'department'), pk=pk) # Apply RBAC filters user = request.user if not user.is_px_admin() and staff.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to view this staff member") context = { 'staff': staff, } return render(request, 'organizations/staff_detail.html', context) @login_required def staff_create(request): """Create staff view""" # Only PX Admins and Hospital Admins can create staff user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to create staff") if request.method == 'POST': form = StaffForm(request.POST) if form.is_valid(): staff = form.save(commit=False) # Handle user account creation create_user = request.POST.get('create_user') == 'on' if create_user and not staff.user and staff.email: from .services import StaffService try: role = StaffService.get_staff_type_role(staff.staff_type) user_account, was_created, password = StaffService.create_user_for_staff( staff, role=role, request=request ) if was_created and password: try: StaffService.send_credentials_email(staff, password, request) messages.success(request, 'Staff member created and credentials email sent successfully.') except Exception as e: messages.warning(request, f'Staff member created but email sending failed: {str(e)}') elif not was_created: messages.success(request, 'Existing user account linked successfully.') except Exception as e: messages.error(request, f'Staff member created but user account creation failed: {str(e)}') staff.save() # Send invitation email if requested if create_user and staff.user and request.POST.get('send_email') != 'false': from .services import StaffService try: password = StaffService.generate_password() staff.user.set_password(password) staff.user.save() StaffService.send_credentials_email(staff, password, request) messages.success(request, 'Credentials email sent successfully.') except Exception as e: messages.warning(request, f'Email sending failed: {str(e)}') messages.success(request, 'Staff member created successfully.') return redirect('organizations:staff_detail', pk=staff.id) else: form = StaffForm(user=request.user) context = { 'form': form, } return render(request, 'organizations/staff_form.html', context) @login_required def staff_update(request, pk): """Update staff view""" staff = get_object_or_404(Staff.objects.select_related('user'), pk=pk) # Apply RBAC filters user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to update this staff member") if user.is_hospital_admin() and staff.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to update this staff member") if request.method == 'POST': form = StaffForm(request.POST, instance=staff) if form.is_valid(): staff = form.save(commit=False) # Handle user account creation create_user = request.POST.get('create_user') == 'on' if create_user and not staff.user and staff.email: from .services import StaffService try: role = StaffService.get_staff_type_role(staff.staff_type) user_account, was_created, password = StaffService.create_user_for_staff( staff, role=role, request=request ) if was_created and password: try: StaffService.send_credentials_email(staff, password, request) messages.success(request, 'User account created and credentials email sent.') except Exception as e: messages.warning(request, f'User account created but email sending failed: {str(e)}') elif not was_created: messages.success(request, 'Existing user account linked successfully.') except Exception as e: messages.error(request, f'User account creation failed: {str(e)}') staff.save() messages.success(request, 'Staff member updated successfully.') return redirect('organizations:staff_detail', pk=staff.id) else: form = StaffForm(instance=staff, user=request.user) context = { 'form': form, 'staff': staff, } return render(request, 'organizations/staff_form.html', context) @login_required def staff_hierarchy(request): """ Staff hierarchy tree view Shows organizational structure based on report_to relationships """ queryset = Staff.objects.select_related('hospital', 'department', 'report_to') # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital: queryset = queryset.filter(hospital=user.hospital) # Apply filters hospital_filter = request.GET.get('hospital') if hospital_filter: queryset = queryset.filter(hospital_id=hospital_filter) department_filter = request.GET.get('department') if department_filter: queryset = queryset.filter(department_id=department_filter) # Search functionality search_query = request.GET.get('search') search_result = None if search_query: try: search_result = Staff.objects.get( Q(employee_id__iexact=search_query) | Q(first_name__icontains=search_query) | Q(last_name__icontains=search_query) ) # If search result exists and user has access, start hierarchy from that staff if search_result and (user.is_px_admin() or search_result.hospital == user.hospital): queryset = Staff.objects.filter( Q(id=search_result.id) | Q(hospital=search_result.hospital) ) except Staff.DoesNotExist: pass # Build hierarchy structure def build_hierarchy(staff_list, parent=None, level=0): """Recursively build hierarchy tree""" result = [] for staff in staff_list: if staff.report_to == parent: node = { 'staff': staff, 'level': level, 'direct_reports': build_hierarchy(staff_list, staff, level + 1), 'has_children': bool(staff.direct_reports.exists()) } result.append(node) return result # Get all staff for the current filter all_staff = list(queryset) # If searching, build hierarchy from search result up if search_result: # Get all managers up the chain manager_chain = [] current = search_result.report_to while current: if current in all_staff: manager_chain.insert(0, current) current = current.report_to # Add search result to chain if search_result not in manager_chain: manager_chain.append(search_result) # Build hierarchy for managers and their reports hierarchy = build_hierarchy(all_staff, parent=None) # Find and highlight search result def find_and_mark(node, target_id, path=None): if path is None: path = [] if node['staff'].id == target_id: node['is_search_result'] = True node['search_path'] = path + [node['staff'].id] return node for child in node['direct_reports']: result = find_and_mark(child, target_id, path + [node['staff'].id]) if result: return result return None search_result_node = None for root in hierarchy: result = find_and_mark(root, search_result.id) if result: search_result_node = result break else: # Build hierarchy starting from top-level (no report_to) hierarchy = build_hierarchy(all_staff, parent=None) # Get hospitals for filter hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) # Get departments for filter departments = Department.objects.filter(status='active') if not user.is_px_admin() and user.hospital: departments = departments.filter(hospital=user.hospital) # Calculate statistics total_staff = queryset.count() top_managers = len(hierarchy) context = { 'hierarchy': hierarchy, 'hospitals': hospitals, 'departments': departments, 'filters': request.GET, 'total_staff': total_staff, 'top_managers': top_managers, 'search_result': search_result, } return render(request, 'organizations/staff_hierarchy.html', context) @login_required def staff_hierarchy_d3(request): """ Staff hierarchy D3 visualization view Shows interactive organizational chart using D3.js """ # Get hospitals for filter (used by client-side filters) hospitals = Hospital.objects.filter(status='active') user = request.user if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) context = { 'hospitals': hospitals, } return render(request, 'organizations/staff_hierarchy_d3.html', context) # ==================== Department CRUD ==================== @login_required def department_create(request): """Create department view""" user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to create departments") if request.method == 'POST': name = request.POST.get('name') name_ar = request.POST.get('name_ar', '') code = request.POST.get('code') hospital_id = request.POST.get('hospital') status = request.POST.get('status', 'active') phone = request.POST.get('phone', '') email = request.POST.get('email', '') location = request.POST.get('location', '') if name and code and hospital_id: # RBAC: Non-admins can only create in their hospital if not user.is_px_admin(): if str(user.hospital_id) != hospital_id: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only create departments in your hospital") department = Department.objects.create( name=name, name_ar=name_ar or name, code=code, hospital_id=hospital_id, status=status, phone=phone, email=email, location=location, ) messages.success(request, 'Department created successfully.') return redirect('organizations:department_list') # Get hospitals for dropdown hospitals = Hospital.objects.filter(status='active') if not user.is_px_admin() and user.hospital: hospitals = hospitals.filter(id=user.hospital.id) context = { 'hospitals': hospitals, } return render(request, 'organizations/department_form.html', context) @login_required def department_update(request, pk): """Update department view""" department = get_object_or_404(Department, pk=pk) user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to update departments") if not user.is_px_admin() and department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only update departments in your hospital") if request.method == 'POST': department.name = request.POST.get('name', department.name) department.name_ar = request.POST.get('name_ar', '') department.code = request.POST.get('code', department.code) department.status = request.POST.get('status', department.status) department.phone = request.POST.get('phone', '') department.email = request.POST.get('email', '') department.location = request.POST.get('location', '') department.save() messages.success(request, 'Department updated successfully.') return redirect('organizations:department_list') context = { 'department': department, } return render(request, 'organizations/department_form.html', context) @login_required def department_delete(request, pk): """Delete department view""" department = get_object_or_404(Department, pk=pk) user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to delete departments") if not user.is_px_admin() and department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only delete departments in your hospital") if request.method == 'POST': # Check for linked staff staff_count = department.staff.count() if staff_count > 0: messages.error(request, f'Cannot delete department. {staff_count} staff members are assigned to it.') return redirect('organizations:department_list') department.delete() messages.success(request, 'Department deleted successfully.') return redirect('organizations:department_list') context = { 'department': department, } return render(request, 'organizations/department_confirm_delete.html', context) # ==================== Staff Section CRUD ==================== @login_required def section_list(request): """Sections list view""" queryset = StaffSection.objects.select_related('department', 'department__hospital', 'head') # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital: queryset = queryset.filter(department__hospital=user.hospital) # Apply filters department_filter = request.GET.get('department') if department_filter: queryset = queryset.filter(department_id=department_filter) status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(name__icontains=search_query) | Q(name_ar__icontains=search_query) | Q(code__icontains=search_query) ) # Ordering queryset = queryset.order_by('department__name', 'name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get departments for filter departments = Department.objects.filter(status='active') if not user.is_px_admin() and user.hospital: departments = departments.filter(hospital=user.hospital) context = { 'page_obj': page_obj, 'sections': page_obj.object_list, 'departments': departments, 'filters': request.GET, } return render(request, 'organizations/section_list.html', context) @login_required def section_create(request): """Create section view""" user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to create sections") if request.method == 'POST': name = request.POST.get('name') name_ar = request.POST.get('name_ar', '') code = request.POST.get('code', '') department_id = request.POST.get('department') status = request.POST.get('status', 'active') head_id = request.POST.get('head') if name and department_id: department = get_object_or_404(Department, pk=department_id) # RBAC check if not user.is_px_admin() and department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only create sections in your hospital") section = StaffSection.objects.create( name=name, name_ar=name_ar or name, code=code, department=department, status=status, head_id=head_id if head_id else None, ) messages.success(request, 'Section created successfully.') return redirect('organizations:section_list') # Get departments for dropdown departments = Department.objects.filter(status='active') if not user.is_px_admin() and user.hospital: departments = departments.filter(hospital=user.hospital) context = { 'departments': departments, } return render(request, 'organizations/section_form.html', context) @login_required def section_update(request, pk): """Update section view""" section = get_object_or_404(StaffSection, pk=pk) user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to update sections") if not user.is_px_admin() and section.department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only update sections in your hospital") if request.method == 'POST': section.name = request.POST.get('name', section.name) section.name_ar = request.POST.get('name_ar', '') section.code = request.POST.get('code', '') section.status = request.POST.get('status', section.status) head_id = request.POST.get('head') section.head_id = head_id if head_id else None section.save() messages.success(request, 'Section updated successfully.') return redirect('organizations:section_list') # Get departments for dropdown departments = Department.objects.filter(status='active') if not user.is_px_admin() and user.hospital: departments = departments.filter(hospital=user.hospital) context = { 'section': section, 'departments': departments, } return render(request, 'organizations/section_form.html', context) @login_required def section_delete(request, pk): """Delete section view""" section = get_object_or_404(StaffSection, pk=pk) user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to delete sections") if not user.is_px_admin() and section.department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only delete sections in your hospital") if request.method == 'POST': subsection_count = section.subsections.count() if subsection_count > 0: messages.error(request, f'Cannot delete section. {subsection_count} subsections are linked to it.') return redirect('organizations:section_list') section.delete() messages.success(request, 'Section deleted successfully.') return redirect('organizations:section_list') context = { 'section': section, } return render(request, 'organizations/section_confirm_delete.html', context) # ==================== Staff Subsection CRUD ==================== @login_required def subsection_list(request): """Subsections list view""" queryset = StaffSubsection.objects.select_related('section', 'section__department', 'section__department__hospital', 'head') # Apply RBAC filters user = request.user if not user.is_px_admin() and user.hospital: queryset = queryset.filter(section__department__hospital=user.hospital) # Apply filters section_filter = request.GET.get('section') if section_filter: queryset = queryset.filter(section_id=section_filter) department_filter = request.GET.get('department') if department_filter: queryset = queryset.filter(section__department_id=department_filter) status_filter = request.GET.get('status') if status_filter: queryset = queryset.filter(status=status_filter) # Search search_query = request.GET.get('search') if search_query: queryset = queryset.filter( Q(name__icontains=search_query) | Q(name_ar__icontains=search_query) | Q(code__icontains=search_query) ) # Ordering queryset = queryset.order_by('section__name', 'name') # Pagination page_size = int(request.GET.get('page_size', 25)) paginator = Paginator(queryset, page_size) page_number = request.GET.get('page', 1) page_obj = paginator.get_page(page_number) # Get sections and departments for filter departments = Department.objects.filter(status='active') sections = StaffSection.objects.filter(status='active') if not user.is_px_admin() and user.hospital: departments = departments.filter(hospital=user.hospital) sections = sections.filter(department__hospital=user.hospital) context = { 'page_obj': page_obj, 'subsections': page_obj.object_list, 'sections': sections, 'departments': departments, 'filters': request.GET, } return render(request, 'organizations/subsection_list.html', context) @login_required def subsection_create(request): """Create subsection view""" user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to create subsections") if request.method == 'POST': name = request.POST.get('name') name_ar = request.POST.get('name_ar', '') code = request.POST.get('code', '') section_id = request.POST.get('section') status = request.POST.get('status', 'active') head_id = request.POST.get('head') if name and section_id: section = get_object_or_404(StaffSection, pk=section_id) # RBAC check if not user.is_px_admin() and section.department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only create subsections in your hospital") subsection = StaffSubsection.objects.create( name=name, name_ar=name_ar or name, code=code, section=section, status=status, head_id=head_id if head_id else None, ) messages.success(request, 'Subsection created successfully.') return redirect('organizations:subsection_list') # Get sections for dropdown sections = StaffSection.objects.filter(status='active').select_related('department') if not user.is_px_admin() and user.hospital: sections = sections.filter(department__hospital=user.hospital) context = { 'sections': sections, } return render(request, 'organizations/subsection_form.html', context) @login_required def subsection_update(request, pk): """Update subsection view""" subsection = get_object_or_404(StaffSubsection, pk=pk) user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to update subsections") if not user.is_px_admin() and subsection.section.department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only update subsections in your hospital") if request.method == 'POST': subsection.name = request.POST.get('name', subsection.name) subsection.name_ar = request.POST.get('name_ar', '') subsection.code = request.POST.get('code', '') subsection.status = request.POST.get('status', subsection.status) head_id = request.POST.get('head') subsection.head_id = head_id if head_id else None subsection.save() messages.success(request, 'Subsection updated successfully.') return redirect('organizations:subsection_list') # Get sections for dropdown sections = StaffSection.objects.filter(status='active').select_related('department') if not user.is_px_admin() and user.hospital: sections = sections.filter(department__hospital=user.hospital) context = { 'subsection': subsection, 'sections': sections, } return render(request, 'organizations/subsection_form.html', context) @login_required def subsection_delete(request, pk): """Delete subsection view""" subsection = get_object_or_404(StaffSubsection, pk=pk) user = request.user if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to delete subsections") if not user.is_px_admin() and subsection.section.department.hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You can only delete subsections in your hospital") if request.method == 'POST': subsection.delete() messages.success(request, 'Subsection deleted successfully.') return redirect('organizations:subsection_list') context = { 'subsection': subsection, } return render(request, 'organizations/subsection_confirm_delete.html', context) @login_required def patient_detail(request, pk): """Patient detail view""" patient = get_object_or_404(Patient.objects.select_related('primary_hospital'), pk=pk) # Apply RBAC filters user = request.user if not user.is_px_admin() and patient.primary_hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to view this patient") # Get patient's survey history from apps.surveys.models import SurveyInstance surveys = SurveyInstance.objects.filter( patient=patient ).select_related('survey_template').order_by('-created_at')[:10] context = { 'patient': patient, 'surveys': surveys, } return render(request, 'organizations/patient_detail.html', context) @login_required def patient_create(request): """Create patient view""" user = request.user # Only PX Admins and Hospital Admins can create patients if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to create patients") if request.method == 'POST': form = PatientForm(user, request.POST) if form.is_valid(): patient = form.save() messages.success(request, f"Patient {patient.get_full_name()} created successfully.") return redirect('organizations:patient_detail', pk=patient.pk) else: form = PatientForm(user) context = { 'form': form, 'title': _('Create Patient'), } return render(request, 'organizations/patient_form.html', context) @login_required def patient_update(request, pk): """Update patient view""" patient = get_object_or_404(Patient, pk=pk) user = request.user # Apply RBAC filters if not user.is_px_admin() and patient.primary_hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to edit this patient") # Only PX Admins and Hospital Admins can update patients if not user.is_px_admin() and not user.is_hospital_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to edit patients") if request.method == 'POST': form = PatientForm(user, request.POST, instance=patient) if form.is_valid(): patient = form.save() messages.success(request, f"Patient {patient.get_full_name()} updated successfully.") return redirect('organizations:patient_detail', pk=patient.pk) else: form = PatientForm(user, instance=patient) context = { 'form': form, 'patient': patient, 'title': _('Edit Patient'), } return render(request, 'organizations/patient_form.html', context) @login_required def patient_delete(request, pk): """Delete patient view""" patient = get_object_or_404(Patient, pk=pk) user = request.user # Apply RBAC filters if not user.is_px_admin() and patient.primary_hospital != user.hospital: from django.http import HttpResponseForbidden return HttpResponseForbidden("You don't have permission to delete this patient") # Only PX Admins can delete patients if not user.is_px_admin(): from django.http import HttpResponseForbidden return HttpResponseForbidden("Only PX Admins can delete patients") if request.method == 'POST': patient_name = patient.get_full_name() patient.delete() messages.success(request, f"Patient {patient_name} deleted successfully.") return redirect('organizations:patient_list') context = { 'patient': patient, } return render(request, 'organizations/patient_confirm_delete.html', context)