from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List from datetime import datetime from app.db.session import get_db from app.schemas.leaves import LeaveRequest, LeaveRequestCreate, LeaveRequestUpdate, LeaveRequestApproval from app.models.leaves import LeaveRequest as LeaveRequestModel, LeaveStatus from app.models.users import User, UserRole from app.models.employees import Employee from app.core.deps import get_current_user, require_role router = APIRouter() @router.post("", response_model=LeaveRequest) def create_leave_request( leave_request: LeaveRequestCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): # Employees can only create leave requests for themselves unless they're HR/Admin if (current_user.role not in [UserRole.ADMIN, UserRole.HR_MANAGER]): current_employee = db.query(Employee).filter(Employee.user_id == current_user.id).first() if not current_employee or leave_request.employee_id != current_employee.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Can only create leave requests for yourself" ) db_leave_request = LeaveRequestModel(**leave_request.dict()) db.add(db_leave_request) db.commit() db.refresh(db_leave_request) return db_leave_request @router.get("", response_model=List[LeaveRequest]) def read_leave_requests( skip: int = 0, limit: int = 100, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): if current_user.role in [UserRole.ADMIN, UserRole.HR_MANAGER]: # HR and Admin can see all leave requests leave_requests = db.query(LeaveRequestModel).offset(skip).limit(limit).all() else: # Employees can only see their own leave requests current_employee = db.query(Employee).filter(Employee.user_id == current_user.id).first() if not current_employee: raise HTTPException(status_code=404, detail="Employee profile not found") leave_requests = db.query(LeaveRequestModel).filter( LeaveRequestModel.employee_id == current_employee.id ).offset(skip).limit(limit).all() return leave_requests @router.get("/{leave_request_id}", response_model=LeaveRequest) def read_leave_request( leave_request_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): leave_request = db.query(LeaveRequestModel).filter(LeaveRequestModel.id == leave_request_id).first() if leave_request is None: raise HTTPException(status_code=404, detail="Leave request not found") # Check permissions if current_user.role not in [UserRole.ADMIN, UserRole.HR_MANAGER]: current_employee = db.query(Employee).filter(Employee.user_id == current_user.id).first() if not current_employee or leave_request.employee_id != current_employee.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions" ) return leave_request @router.put("/{leave_request_id}/approve", response_model=LeaveRequest) def approve_leave_request( leave_request_id: int, approval: LeaveRequestApproval, db: Session = Depends(get_db), current_user: User = Depends(require_role([UserRole.ADMIN, UserRole.HR_MANAGER, UserRole.MANAGER])) ): leave_request = db.query(LeaveRequestModel).filter(LeaveRequestModel.id == leave_request_id).first() if leave_request is None: raise HTTPException(status_code=404, detail="Leave request not found") leave_request.status = approval.status leave_request.comments = approval.comments leave_request.approved_by = current_user.id leave_request.approved_at = datetime.utcnow() db.commit() db.refresh(leave_request) return leave_request @router.put("/{leave_request_id}", response_model=LeaveRequest) def update_leave_request( leave_request_id: int, leave_request_update: LeaveRequestUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): leave_request = db.query(LeaveRequestModel).filter(LeaveRequestModel.id == leave_request_id).first() if leave_request is None: raise HTTPException(status_code=404, detail="Leave request not found") # Only allow updates if pending and user owns the request or is HR/Admin if leave_request.status != LeaveStatus.PENDING: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Can only update pending leave requests" ) if current_user.role not in [UserRole.ADMIN, UserRole.HR_MANAGER]: current_employee = db.query(Employee).filter(Employee.user_id == current_user.id).first() if not current_employee or leave_request.employee_id != current_employee.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions" ) update_data = leave_request_update.dict(exclude_unset=True) for field, value in update_data.items(): setattr(leave_request, field, value) db.commit() db.refresh(leave_request) return leave_request @router.delete("/{leave_request_id}") def delete_leave_request( leave_request_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_user) ): leave_request = db.query(LeaveRequestModel).filter(LeaveRequestModel.id == leave_request_id).first() if leave_request is None: raise HTTPException(status_code=404, detail="Leave request not found") # Check permissions if current_user.role not in [UserRole.ADMIN, UserRole.HR_MANAGER]: current_employee = db.query(Employee).filter(Employee.user_id == current_user.id).first() if not current_employee or leave_request.employee_id != current_employee.id: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not enough permissions" ) db.delete(leave_request) db.commit() return {"message": "Leave request deleted successfully"}