DocUA's picture
add .env
2929135
raw
history blame
6.32 kB
# 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:
@tool
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
@tool
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
@tool
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