""" Mandate routes for the backend API. Implements the endpoints for mandate management. """ from fastapi import APIRouter, HTTPException, Depends, Body, Path, Request, Response from typing import List, Dict, Any, Optional from fastapi import status import logging # Import auth module from modules.security.auth import limiter, getCurrentUser # Import interfaces import modules.interfaces.serviceManagementClass as serviceManagementClass from modules.shared.attributeUtils import getModelAttributeDefinitions # Import the model classes from modules.interfaces.serviceAppModel import AttributeDefinition, Mandate, User # Configure logger logger = logging.getLogger(__name__) # Model attributes for Mandate mandateAttributes = getModelAttributeDefinitions(Mandate) # Create a router for the mandate endpoints router = APIRouter( prefix="/api/mandates", tags=["Manage Mandates"], responses={404: {"description": "Not found"}} ) @router.get("/", response_model=List[Mandate]) @limiter.limit("30/minute") async def get_mandates( request: Request, currentUser: User = Depends(getCurrentUser) ) -> List[Mandate]: """Get all mandates""" try: managementInterface = serviceManagementClass.getInterface(currentUser) mandates = managementInterface.getMandates() return [Mandate.from_dict(mandate) for mandate in mandates] except Exception as e: logger.error(f"Error getting mandates: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to get mandates: {str(e)}" ) @router.get("/{mandateId}", response_model=Mandate) @limiter.limit("30/minute") async def get_mandate( request: Request, mandateId: str = Path(..., description="ID of the mandate"), currentUser: User = Depends(getCurrentUser) ) -> Mandate: """Get a specific mandate by ID""" try: managementInterface = serviceManagementClass.getInterface(currentUser) mandate = managementInterface.getMandate(mandateId) if not mandate: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Mandate with ID {mandateId} not found" ) return Mandate.from_dict(mandate) except HTTPException: raise except Exception as e: logger.error(f"Error getting mandate {mandateId}: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to get mandate: {str(e)}" ) @router.post("/", response_model=Mandate) @limiter.limit("10/minute") async def create_mandate( request: Request, mandateData: Mandate = Body(...), currentUser: User = Depends(getCurrentUser) ) -> Mandate: """Create a new mandate""" try: managementInterface = serviceManagementClass.getInterface(currentUser) # Convert Mandate to dict for interface mandate_data = mandateData.to_dict() # Create mandate newMandate = managementInterface.createMandate(mandate_data) if not newMandate: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to create mandate" ) return Mandate.from_dict(newMandate) except HTTPException: raise except Exception as e: logger.error(f"Error creating mandate: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to create mandate: {str(e)}" ) @router.put("/{mandateId}", response_model=Mandate) @limiter.limit("10/minute") async def update_mandate( request: Request, mandateId: str = Path(..., description="ID of the mandate to update"), mandateData: Mandate = Body(...), currentUser: User = Depends(getCurrentUser) ) -> Mandate: """Update an existing mandate""" try: managementInterface = serviceManagementClass.getInterface(currentUser) # Check if mandate exists existingMandate = managementInterface.getMandate(mandateId) if not existingMandate: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Mandate with ID {mandateId} not found" ) # Convert Mandate to dict for interface update_data = mandateData.to_dict() # Update mandate updatedMandate = managementInterface.updateMandate(mandateId, update_data) if not updatedMandate: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail="Failed to update mandate" ) return Mandate.from_dict(updatedMandate) except HTTPException: raise except Exception as e: logger.error(f"Error updating mandate {mandateId}: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to update mandate: {str(e)}" ) @router.delete("/{mandateId}", response_model=Dict[str, Any]) @limiter.limit("10/minute") async def delete_mandate( request: Request, mandateId: str = Path(..., description="ID of the mandate to delete"), currentUser: User = Depends(getCurrentUser) ) -> Dict[str, Any]: """Delete a mandate""" try: appInterface = serviceManagementClass.getInterface(currentUser) # Check if mandate exists existingMandate = appInterface.getMandateById(mandateId) if not existingMandate: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail=f"Mandate {mandateId} not found" ) # Delete mandate try: appInterface.deleteMandate(mandateId) except ValueError as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail=str(e) ) return {"message": f"Mandate {mandateId} deleted successfully"} except HTTPException: raise except Exception as e: logger.error(f"Error deleting mandate {mandateId}: {str(e)}") raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=f"Failed to delete mandate: {str(e)}" ) @router.get("/attributes", response_model=List[AttributeDefinition]) @limiter.limit("30/minute") async def get_mandate_attributes( request: Request, currentUser: User = Depends(getCurrentUser) ) -> List[AttributeDefinition]: """ Retrieves the attribute definitions for mandates. This can be used for dynamic form generation. Returns: - A list of attribute definitions that can be used to generate forms """ # Get attributes from the Mandate model class return Mandate.getModelAttributeDefinitions()