Spaces:
Sleeping
Sleeping
| from fastapi import APIRouter, HTTPException, Depends, status | |
| from fastapi.security import HTTPBearer | |
| from app.models.guest_model import GuestModel | |
| from app.schemas.guest_schema import ( | |
| GuestCreateRequest, | |
| GuestUpdateRequest, | |
| GuestResponse, | |
| GuestListResponse, | |
| GuestDeleteResponse, | |
| SetDefaultGuestRequest | |
| ) | |
| from app.utils.jwt import verify_token | |
| from typing import Dict, Any | |
| import logging | |
| logger = logging.getLogger(__name__) | |
| router = APIRouter() | |
| security = HTTPBearer() | |
| async def get_current_user(token: str = Depends(security)) -> Dict[str, Any]: | |
| """ | |
| Dependency to get current authenticated user from JWT token | |
| """ | |
| try: | |
| payload = verify_token(token.credentials) | |
| if not payload: | |
| raise HTTPException( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| detail="Invalid or expired token" | |
| ) | |
| return payload | |
| except Exception as e: | |
| logger.error(f"Token verification failed: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_401_UNAUTHORIZED, | |
| detail="Invalid or expired token" | |
| ) | |
| async def get_user_guests( | |
| current_user: Dict[str, Any] = Depends(get_current_user) | |
| ): | |
| """ | |
| Get all guests for a specific user. | |
| - **customer_id**: ID of the user | |
| - Returns list of guests with total count | |
| """ | |
| try: | |
| # Verify user can only access their own guests | |
| customer_id=current_user.get("sub") | |
| guests_data = await GuestModel.get_user_guests(customer_id) | |
| guests = [GuestResponse(**guest) for guest in guests_data] | |
| return GuestListResponse( | |
| guests=guests, | |
| total_count=len(guests) | |
| ) | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error getting guests for user {customer_id}: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to retrieve guests" | |
| ) | |
| async def create_guest( | |
| guest_data: GuestCreateRequest, | |
| current_user: Dict[str, Any] = Depends(get_current_user) | |
| ): | |
| """ | |
| Create a new guest profile for a user. | |
| - **customer_id**: ID of the user creating the guest profile | |
| - **guest_data**: Guest information including name, contact details, etc. | |
| - Returns the created guest profile | |
| """ | |
| try: | |
| # Verify user can only create guests for themselves | |
| customer_id=current_user.get("sub") | |
| # Create guest in database | |
| guest_id=await GuestModel.create_guest(customer_id,guest_data.dict()) | |
| if not guest_id: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to create guest profile" | |
| ) | |
| # Retrieve and return the created guest | |
| created_guest = await GuestModel.get_guest_by_id(customer_id, guest_id) | |
| if not created_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Guest created but failed to retrieve" | |
| ) | |
| return GuestResponse(**created_guest) | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error creating guest for user {customer_id}: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to create guest profile" | |
| ) | |
| async def get_default_guest( | |
| current_user: Dict[str, Any] = Depends(get_current_user) | |
| ): | |
| """Get the default guest for the current user""" | |
| try: | |
| customer_id = current_user.get("sub") | |
| default_guest = await GuestModel.get_default_guest(customer_id) | |
| if not default_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Default guest not set" | |
| ) | |
| return GuestResponse(**default_guest) | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error getting default guest for user {customer_id}: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to retrieve default guest" | |
| ) | |
| async def set_default_guest( | |
| req: SetDefaultGuestRequest, | |
| current_user: Dict[str, Any] = Depends(get_current_user) | |
| ): | |
| """Set a guest as default for the current user""" | |
| try: | |
| customer_id = current_user.get("sub") | |
| # Verify guest exists and belongs to user | |
| existing_guest = await GuestModel.get_guest_by_id(customer_id, req.guest_id) | |
| if not existing_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Guest not found" | |
| ) | |
| if existing_guest.get("customer_id") != customer_id: | |
| raise HTTPException( | |
| status_code=status.HTTP_403_FORBIDDEN, | |
| detail="Access denied. This guest doesn't belong to you." | |
| ) | |
| success = await GuestModel.set_default_guest(customer_id, req.guest_id) | |
| if not success: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to set default guest" | |
| ) | |
| updated_guest = await GuestModel.get_guest_by_id(customer_id, req.guest_id) | |
| if not updated_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Default set but failed to retrieve guest" | |
| ) | |
| return GuestResponse(**updated_guest) | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error setting default guest {req.guest_id} for user {customer_id}: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to set default guest" | |
| ) | |
| async def update_guest( | |
| guest_id: str, | |
| guest_data: GuestUpdateRequest, | |
| current_user: Dict[str, Any] = Depends(get_current_user) | |
| ): | |
| """ | |
| Update an existing guest profile. | |
| - **customer_id**: ID of the user who owns the guest profile | |
| - **guest_id**: ID of the guest to update | |
| - **guest_data**: Updated guest information | |
| - Returns the updated guest profile | |
| """ | |
| try: | |
| # Verify user can only update their own guests | |
| customer_id=current_user.get("sub") | |
| # Check if guest exists and belongs to user | |
| existing_guest = await GuestModel.get_guest_by_id(customer_id, guest_id) | |
| if not existing_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Guest not found" | |
| ) | |
| if existing_guest.get("customer_id") != customer_id: | |
| raise HTTPException( | |
| status_code=status.HTTP_403_FORBIDDEN, | |
| detail="Access denied. This guest doesn't belong to you." | |
| ) | |
| # Prepare update fields (only include non-None values) | |
| update_fields = {} | |
| for field, value in guest_data.dict(exclude_unset=True).items(): | |
| if value is not None: | |
| if hasattr(value, 'value'): # Handle enum values | |
| update_fields[field] = value.value | |
| else: | |
| update_fields[field] = value | |
| if not update_fields: | |
| raise HTTPException( | |
| status_code=status.HTTP_400_BAD_REQUEST, | |
| detail="No valid fields provided for update" | |
| ) | |
| # Update guest in database | |
| success = await GuestModel.update_guest(customer_id, guest_id, update_fields) | |
| if not success: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to update guest profile" | |
| ) | |
| # Retrieve and return updated guest | |
| updated_guest = await GuestModel.get_guest_by_id(customer_id, guest_id) | |
| if not updated_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Guest updated but failed to retrieve" | |
| ) | |
| return GuestResponse(**updated_guest) | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error updating guest {guest_id} for user {customer_id}: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to update guest profile" | |
| ) | |
| async def delete_guest( | |
| guest_id: str, | |
| current_user: Dict[str, Any] = Depends(get_current_user) | |
| ): | |
| """ | |
| Delete a guest profile. | |
| - **customer_id**: ID of the user who owns the guest profile | |
| - **guest_id**: ID of the guest to delete | |
| - Returns confirmation of deletion | |
| """ | |
| try: | |
| # Verify user can only delete their own guests | |
| customer_id=current_user.get("sub") | |
| # Check if guest exists and belongs to user | |
| existing_guest = await GuestModel.get_guest_by_id(customer_id, guest_id) | |
| if not existing_guest: | |
| raise HTTPException( | |
| status_code=status.HTTP_404_NOT_FOUND, | |
| detail="Guest not found" | |
| ) | |
| if existing_guest.get("customer_id") != customer_id: | |
| raise HTTPException( | |
| status_code=status.HTTP_403_FORBIDDEN, | |
| detail="Access denied. This guest doesn't belong to you." | |
| ) | |
| # Delete guest from database | |
| success = await GuestModel.delete_guest(customer_id, guest_id) | |
| if not success: | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to delete guest profile" | |
| ) | |
| guest_name = existing_guest.get('first_name', 'Guest') | |
| if existing_guest.get('last_name'): | |
| guest_name += f" {existing_guest.get('last_name')}" | |
| return GuestDeleteResponse( | |
| message=f"Guest '{guest_name}' has been successfully deleted", | |
| guest_id=guest_id | |
| ) | |
| except HTTPException: | |
| raise | |
| except Exception as e: | |
| logger.error(f"Error deleting guest {guest_id} for user {customer_id}: {str(e)}") | |
| raise HTTPException( | |
| status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, | |
| detail="Failed to delete guest profile" | |
| ) |