Admin-Desk2 / app /api /staff_analytics.py
Fred808's picture
Upload 94 files
1f8ac0c verified
from fastapi import APIRouter, Depends, Query, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from datetime import datetime
from typing import Dict, Any, Optional, List
from ..core.dependencies import get_current_active_user, get_db
from ..db.models import User, ActivityType
from ..services.analytics import staff_analytics
from ..services.staff_reports import staff_reports
from ..services.performance_notifications import performance_notifications
from ..db.schemas import (
StaffActivityCreate,
StaffActivityInDB,
StaffPerformanceReport,
RealtimeStaffMetrics
)
router = APIRouter()
@router.post("/activity", response_model=Dict[str, Any])
async def record_staff_activity(
activity: StaffActivityCreate,
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Record a staff activity"""
if not current_user.branch_id:
raise HTTPException(status_code=400, detail="User is not associated with a branch")
recorded_activity, prev_metrics, new_metrics = await staff_analytics.record_activity(
user_id=current_user.id,
branch_id=current_user.branch_id,
activity_type=activity.activity_type,
details=activity.details,
duration=activity.duration
)
# Process notifications for the activity
await performance_notifications.process_activity_notifications(
user_id=current_user.id,
branch_id=current_user.branch_id,
activity=recorded_activity,
prev_metrics=prev_metrics,
new_metrics=new_metrics
)
return {
"status": "success",
"activity_id": recorded_activity.id,
"performance_score": recorded_activity.performance_score
}
@router.get("/performance", response_model=StaffPerformanceReport)
async def get_staff_performance(
branch_id: Optional[int] = Query(None, description="Filter by branch ID"),
user_id: Optional[int] = Query(None, description="Filter by user ID"),
start_date: Optional[datetime] = Query(None, description="Start date for analysis"),
end_date: Optional[datetime] = Query(None, description="End date for analysis"),
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Get staff performance metrics"""
# Check permissions
if not current_user.is_superuser and (
(branch_id and branch_id != current_user.branch_id) or
(user_id and user_id != current_user.id)
):
raise HTTPException(
status_code=403,
detail="You can only view performance metrics for your own branch"
)
# Non-superusers can only view their branch
if not current_user.is_superuser:
branch_id = current_user.branch_id
return await staff_analytics.get_staff_performance(
branch_id=branch_id,
user_id=user_id,
start_date=start_date,
end_date=end_date
)
@router.get("/metrics/summary")
async def get_performance_summary(
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Get a summary of current user's performance metrics"""
metrics = await staff_analytics.get_staff_performance(
user_id=current_user.id,
branch_id=current_user.branch_id
)
# Get user's performance data
user_metrics = next(
(p for p in metrics["staff_performance"] if p["user_id"] == current_user.id),
None
)
if not user_metrics:
return {
"message": "No performance metrics available",
"metrics": None
}
# Get comparison with branch averages
comparison = await staff_reports.generate_staff_comparison(
user_id=current_user.id,
branch_id=current_user.branch_id
)
return {
"metrics": user_metrics["metrics"],
"comparison": comparison,
"period": metrics["date_range"]
}
@router.get("/realtime", response_model=RealtimeStaffMetrics)
async def get_realtime_activity(
branch_id: Optional[int] = Query(None, description="Filter by branch ID"),
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Get real-time staff activity for the current day"""
if not current_user.is_superuser and branch_id != current_user.branch_id:
raise HTTPException(
status_code=403,
detail="You can only view real-time activity for your own branch"
)
today = datetime.utcnow()
today_start = today.replace(hour=0, minute=0, second=0, microsecond=0)
metrics = await staff_analytics.get_staff_performance(
branch_id=branch_id or current_user.branch_id,
start_date=today_start,
end_date=today
)
# Calculate real-time metrics
active_staff = [
staff for staff in metrics["staff_performance"]
if staff["metrics"]["total_login_time"] > 0
]
total_sales_today = sum(
staff["metrics"]["total_sales"] for staff in metrics["staff_performance"]
)
total_transactions = sum(
staff["metrics"]["transaction_count"] for staff in metrics["staff_performance"]
)
return {
"active_staff_count": len(active_staff),
"total_sales_today": total_sales_today,
"total_transactions": total_transactions,
"staff_metrics": active_staff,
"last_updated": datetime.utcnow().isoformat()
}
@router.get("/reports/performance")
async def get_performance_report(
branch_id: Optional[int] = Query(None, description="Filter by branch ID"),
start_date: Optional[datetime] = Query(None, description="Start date for report"),
end_date: Optional[datetime] = Query(None, description="End date for report"),
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Generate comprehensive performance report with insights"""
# Check permissions
if not current_user.is_superuser and branch_id != current_user.branch_id:
raise HTTPException(
status_code=403,
detail="You can only view reports for your own branch"
)
return await staff_reports.generate_performance_report(
branch_id=branch_id or current_user.branch_id,
start_date=start_date,
end_date=end_date
)
@router.get("/reports/comparison")
async def get_staff_comparison(
user_id: Optional[int] = Query(None, description="User ID to compare (defaults to current user)"),
date: Optional[datetime] = Query(None, description="Date for comparison"),
current_user: User = Depends(get_current_active_user),
db: AsyncSession = Depends(get_db)
) -> Dict[str, Any]:
"""Get performance comparison against branch averages"""
if not current_user.is_superuser and user_id != current_user.id:
raise HTTPException(
status_code=403,
detail="You can only view your own performance comparison"
)
return await staff_reports.generate_staff_comparison(
user_id=user_id or current_user.id,
branch_id=current_user.branch_id,
date=date
)