""" Diagnostic script to check staff hierarchy data """ import os import sys import django # Setup Django os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'PX360.settings') sys.path.insert(0, '/home/ismail/projects/HH') django.setup() from apps.organizations.models import Staff, Hospital, Department from django.db.models import Count, Q print("=" * 80) print("STAFF HIERARCHY DIAGNOSTIC REPORT") print("=" * 80) # 1. Check if staff data exists print("\n1. STAFF DATA CHECK") print("-" * 80) total_staff = Staff.objects.count() print(f"Total staff members in database: {total_staff}") if total_staff == 0: print("\n❌ NO STAFF DATA FOUND") print(" The staff hierarchy cannot be displayed because no staff data exists.") print(" Please import staff data using:") print(" python manage.py import_staff_csv sample_staff_data.csv --hospital-code ALH") sys.exit(0) # Check active staff active_staff = Staff.objects.filter(status='active').count() print(f"Active staff members: {active_staff}") # 2. Check manager relationships print("\n2. MANAGER RELATIONSHIP CHECK") print("-" * 80) with_manager = Staff.objects.filter(report_to__isnull=False).count() without_manager = total_staff - with_manager print(f"Staff WITH manager assigned: {with_manager}") print(f"Staff WITHOUT manager assigned: {without_manager}") if with_manager == 0: print("\n⚠️ WARNING: No staff have manager relationships assigned") print(" The hierarchy requires staff to have report_to relationships set.") # 3. Check for broken relationships print("\n3. BROKEN RELATIONSHIP CHECK") print("-" * 80) broken_relationships = Staff.objects.exclude(report_to__isnull=True).exclude( report_to__in=Staff.objects.all() ).count() print(f"Staff with broken manager references: {broken_relationships}") if broken_relationships > 0: print("\n⚠️ WARNING: Found staff with references to non-existent managers") broken_staff = Staff.objects.exclude(report_to__isnull=True).exclude( report_to__in=Staff.objects.all() ).select_related('report_to')[:5] print(" Examples:") for staff in broken_staff: print(f" - {staff.name} (ID: {staff.employee_id}) references manager ID: {staff.report_to_id}") # 4. Check hospital and department assignments print("\n4. ORGANIZATION STRUCTURE CHECK") print("-" * 80) hospitals = Hospital.objects.count() departments = Department.objects.count() print(f"Hospitals: {hospitals}") print(f"Departments: {departments}") staff_with_hospital = Staff.objects.filter(hospital__isnull=False).count() staff_with_department = Staff.objects.filter(department__isnull=False).count() print(f"Staff with hospital assigned: {staff_with_hospital}") print(f"Staff with department assigned: {staff_with_department}") # 5. Analyze hierarchy structure print("\n5. HIERARCHY STRUCTURE ANALYSIS") print("-" * 80) # Find potential root nodes (no manager OR manager not in same hospital) all_staff_ids = set(Staff.objects.values_list('id', flat=True)) root_candidates = Staff.objects.filter( Q(report_to__isnull=True) | ~Q(report_to__in=all_staff_ids) ) print(f"Potential root nodes (no manager or manager outside set): {root_candidates.count()}") # Count staff by hierarchy level print("\nStaff by number of direct reports:") report_counts = Staff.objects.annotate( report_count=Count('direct_reports') ).values('report_count').annotate(count=Count('id')).order_by('-report_count') for rc in report_counts: count = rc['report_count'] num_staff = rc['count'] label = f"{count} reports" if count > 0 else "No reports (leaf nodes)" print(f" {label}: {num_staff}") # 6. Sample hierarchy data print("\n6. SAMPLE HIERARCHY DATA") print("-" * 80) sample_staff = Staff.objects.select_related('report_to', 'hospital', 'department')[:5] for staff in sample_staff: manager_info = f"→ {staff.report_to.name}" if staff.report_to else "(No manager)" print(f"{staff.name} ({staff.employee_id}) {manager_info}") print(f" Hospital: {staff.hospital.name if staff.hospital else 'None'}") print(f" Department: {staff.department.name if staff.department else 'None'}") print() # 7. Test hierarchy building logic print("\n7. HIERARCHY BUILDING TEST") print("-" * 80) staff_list = list(Staff.objects.select_related('report_to')) staff_dict = {staff.id: staff for staff in staff_list} # Find root nodes (matching API logic) root_staff = [ staff for staff in staff_list if staff.report_to_id is None or staff.report_to_id not in staff_dict ] print(f"Root nodes detected by API logic: {len(root_staff)}") if root_staff: print("\nRoot nodes:") for i, staff in enumerate(root_staff[:10], 1): # Count total team size def count_team(staff_id): count = 1 reports = [s for s in staff_list if s.report_to_id == staff_id] for r in reports: count += count_team(r.id) return count team_size = count_team(staff.id) print(f" {i}. {staff.name} (ID: {staff.employee_id}) - Team size: {team_size}") # 8. Summary and recommendations print("\n" + "=" * 80) print("DIAGNOSTIC SUMMARY") print("=" * 80) issues = [] if total_staff == 0: issues.append("❌ No staff data exists") elif with_manager == 0: issues.append("❌ No manager relationships assigned") elif broken_relationships > 0: issues.append(f"⚠️ {broken_relationships} broken manager references") elif len(root_staff) == 0: issues.append("❌ No root nodes found in hierarchy") elif len(root_staff) > 10: issues.append(f"⚠️ Many disconnected hierarchies ({len(root_staff)} root nodes)") if issues: print("\nISSUES FOUND:") for issue in issues: print(f" {issue}") else: print("\n✓ No critical issues detected") print(" Staff data exists and hierarchy structure appears valid") print("\n" + "=" * 80)