HH/diagnose_hierarchy.py

173 lines
5.8 KiB
Python

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