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 )