Spaces:
Sleeping
Sleeping
# src/tools/scheduling_tools.py | |
#from typing import Dict, List, Optional | |
from typing import Dict, List, Optional, Any | |
from typing_extensions import TypedDict # If using TypedDict | |
from langchain_core.tools import tool | |
from datetime import datetime, timedelta | |
from ..utils.logger import setup_logger | |
logger = setup_logger(__name__) | |
class SchedulingTools: | |
def optimize_staff_schedule( | |
self, | |
staff_availability: List[Dict], | |
department_needs: Dict[str, Dict], | |
shift_preferences: Optional[List[Dict]] = None | |
) -> Dict: | |
"""Generate optimized staff schedules based on availability and department needs""" | |
try: | |
schedule = { | |
"shifts": {}, | |
"coverage_gaps": [], | |
"recommendations": [], | |
"staff_assignments": {} | |
} | |
# Process each department's needs | |
for dept, needs in department_needs.items(): | |
schedule["shifts"][dept] = { | |
"morning": [], | |
"afternoon": [], | |
"night": [] | |
} | |
required_staff = needs.get("required_staff", {}) | |
# Match available staff to shifts | |
for staff in staff_availability: | |
if staff["department"] == dept and staff["available"]: | |
preferred_shift = "morning" # Default | |
if shift_preferences: | |
for pref in shift_preferences: | |
if pref["staff_id"] == staff["id"]: | |
preferred_shift = pref["preferred_shift"] | |
schedule["shifts"][dept][preferred_shift].append(staff["id"]) | |
# Identify coverage gaps | |
for shift in ["morning", "afternoon", "night"]: | |
required = required_staff.get(shift, 0) | |
assigned = len(schedule["shifts"][dept][shift]) | |
if assigned < required: | |
schedule["coverage_gaps"].append({ | |
"department": dept, | |
"shift": shift, | |
"shortage": required - assigned | |
}) | |
return schedule | |
except Exception as e: | |
logger.error(f"Error optimizing staff schedule: {str(e)}") | |
raise | |
def analyze_workforce_metrics( | |
self, | |
staff_data: List[Dict], | |
time_period: str | |
) -> Dict: | |
"""Analyze workforce metrics including overtime, satisfaction, and skill mix""" | |
try: | |
analysis = { | |
"workforce_metrics": { | |
"total_staff": len(staff_data), | |
"overtime_hours": 0, | |
"skill_distribution": {}, | |
"satisfaction_score": 0, | |
"turnover_rate": 0 | |
}, | |
"recommendations": [] | |
} | |
total_satisfaction = 0 | |
total_overtime = 0 | |
for staff in staff_data: | |
# Analyze overtime | |
total_overtime += staff.get("overtime_hours", 0) | |
# Track skill distribution | |
role = staff.get("role", "unknown") | |
analysis["workforce_metrics"]["skill_distribution"][role] = \ | |
analysis["workforce_metrics"]["skill_distribution"].get(role, 0) + 1 | |
# Track satisfaction | |
total_satisfaction += staff.get("satisfaction_score", 0) | |
# Calculate averages | |
if staff_data: | |
analysis["workforce_metrics"]["overtime_hours"] = total_overtime / len(staff_data) | |
analysis["workforce_metrics"]["satisfaction_score"] = \ | |
total_satisfaction / len(staff_data) | |
# Generate recommendations | |
if analysis["workforce_metrics"]["overtime_hours"] > 10: | |
analysis["recommendations"].append("Reduce overtime hours through better scheduling") | |
if analysis["workforce_metrics"]["satisfaction_score"] < 7: | |
analysis["recommendations"].append("Implement staff satisfaction improvement measures") | |
return analysis | |
except Exception as e: | |
logger.error(f"Error analyzing workforce metrics: {str(e)}") | |
raise | |
def calculate_staffing_needs( | |
self, | |
patient_census: Dict[str, int], | |
acuity_levels: Dict[str, float], | |
staff_ratios: Dict[str, float] | |
) -> Dict: | |
"""Calculate staffing needs based on patient census and acuity""" | |
try: | |
staffing_needs = { | |
"required_staff": {}, | |
"current_gaps": {}, | |
"recommendations": [] | |
} | |
for department, census in patient_census.items(): | |
# Calculate base staffing need | |
acuity = acuity_levels.get(department, 1.0) | |
ratio = staff_ratios.get(department, 4) # default 1:4 ratio | |
required_staff = ceil(census * acuity / ratio) | |
staffing_needs["required_staff"][department] = { | |
"total_needed": required_staff, | |
"acuity_factor": acuity, | |
"patient_ratio": ratio | |
} | |
# Generate staffing recommendations | |
if required_staff > current_staff.get(department, 0): | |
staffing_needs["recommendations"].append({ | |
"department": department, | |
"action": "increase_staff", | |
"amount": required_staff - current_staff.get(department, 0) | |
}) | |
return staffing_needs | |
except Exception as e: | |
logger.error(f"Error calculating staffing needs: {str(e)}") | |
raise# scheduling_tools implementation | |