from typing import List, Optional, Dict, Any, Union from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, Query, Path from sqlalchemy.orm import Session from app.api.dependencies.auth import get_current_active_user, get_current_user from app.crud.gift import gift_item_crud, gift_category_crud, gift_purchase_crud, event_gift_category_crud from app.crud.guest import guest_crud from app.crud.event import event_crud from app.models.gift import GiftStatus, GiftPriority, EventGiftCategory, GiftItem from app.models.user import User from app.schemas.gifts import ( GiftItem, GiftItemCreate, GiftItemUpdate, GiftCategory, GiftCategoryCreate, GiftCategoryUpdate, GiftPurchase, GiftPurchaseCreate, GiftPurchaseUpdate, EventGiftCategoryCreate, EventGiftCategoryUpdate, EventGiftCategoryInDB ) from app.core.database import get_db router = APIRouter() # ===== GIFT CATEGORIES ===== # @router.post("/categories/", response_model=GiftCategory) def create_gift_category( *, db: Session = Depends(get_db), category_in: GiftCategoryCreate, event_id: UUID, current_user: User = Depends(get_current_active_user) ) -> Any: """ Create new gift category and associate it with an event. """ # Check if user has permission to manage this event event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) # In a complete system, use the EventManager permissions if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # Create the category category = gift_category_crud.create(db, obj_in=category_in) # Create the association between the category and the event association_data = EventGiftCategoryCreate( event_id=event_id, category_id=category.id, display_order=0, # Default display order is_visible=True # Default visibility ) event_gift_category_crud.create(db, obj_in=association_data) # Set display properties for the response category.display_order = 0 category.is_visible = True return category @router.get("/categories/event/{event_id}", response_model=List[GiftCategory]) def read_gift_categories( *, db: Session = Depends(get_db), event_id: UUID = Path(...), skip: int = 0, limit: int = 100, include_hidden: bool = False, include_gifts: bool = False, current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Retrieve gift categories for an event. """ # Check if event exists and is accessible event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # For public access, ensure event is public if not current_user and not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") # Get categories for this event using the association table categories = event_gift_category_crud.get_categories_by_event( db, event_id=event_id, skip=skip, limit=limit, include_hidden=include_hidden ) # Enhance categories with display information from the association for category in categories: # Get the association to access display_order and is_visible association = event_gift_category_crud.get( db, event_id=event_id, category_id=category.id ) if association: category.display_order = association.display_order category.is_visible = association.is_visible # Calculate statistics for this event total_gifts = 0 available_gifts = 0 if category.gifts: for gift in category.gifts: if gift.event_id == event_id: total_gifts += 1 if gift.status == GiftStatus.AVAILABLE and gift.is_visible: available_gifts += 1 category.total_gifts = total_gifts category.available_gifts = available_gifts # If include_gifts is true, fetch gift items for each category if include_gifts: for category in categories: gifts = gift_item_crud.get_multi_by_event( db, event_id=event_id, category_id=category.id, include_hidden=include_hidden ) # Set the gifts attribute which is initially None in the model setattr(category, "gifts", gifts) return categories @router.get("/categories/{category_id}", response_model=GiftCategory) def read_gift_category( *, db: Session = Depends(get_db), category_id: UUID = Path(...), event_id: Optional[UUID] = None, include_gifts: bool = False, current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Get gift category by ID. If event_id is provided, includes event-specific display settings. """ category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Initialize event-specific properties category.display_order = None category.is_visible = None category.total_gifts = None category.available_gifts = None # If event_id is provided, get event-specific information if event_id: # Check if event exists and is accessible event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # For public access, ensure event is public if not event.is_public and not current_user: raise HTTPException(status_code=403, detail="Not enough permissions") # Check if this category is associated with the event association = event_gift_category_crud.get(db, event_id=event_id, category_id=category_id) if not association: raise HTTPException(status_code=404, detail="Category not associated with this event") # Set event-specific display properties category.display_order = association.display_order category.is_visible = association.is_visible # Calculate statistics for this event total_gifts = 0 available_gifts = 0 # If include_gifts is true, fetch gift items for the category in this event if include_gifts: gifts = gift_item_crud.get_multi_by_event( db, event_id=event_id, category_id=category.id, include_hidden=current_user is not None # Only include hidden for logged-in users ) # Set the gifts attribute setattr(category, "gifts", gifts) # Calculate statistics for gift in gifts: total_gifts += 1 if gift.status == GiftStatus.AVAILABLE and gift.is_visible: available_gifts += 1 else: # Calculate statistics without fetching all gifts gifts_query = db.query(GiftItem).filter( GiftItem.event_id == event_id, GiftItem.category_id == category_id ) total_gifts = gifts_query.count() available_gifts = gifts_query.filter( GiftItem.status == GiftStatus.AVAILABLE, GiftItem.is_visible == True ).count() category.total_gifts = total_gifts category.available_gifts = available_gifts elif include_gifts: # If no event_id but include_gifts is true, just get all gifts for this category # This is less useful without event context but included for completeness gifts = db.query(GiftItem).filter(GiftItem.category_id == category_id).all() setattr(category, "gifts", gifts) return category @router.put("/categories/{category_id}", response_model=GiftCategory) def update_gift_category( *, db: Session = Depends(get_db), category_id: UUID = Path(...), category_in: GiftCategoryUpdate, event_id: Optional[UUID] = None, current_user: User = Depends(get_current_active_user) ) -> Any: """ Update a gift category. If event_id is provided, also updates the event-specific settings. """ category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Update the category itself updated_category = gift_category_crud.update(db, db_obj=category, obj_in=category_in) # Initialize event-specific properties for the response updated_category.display_order = None updated_category.is_visible = None updated_category.total_gifts = None updated_category.available_gifts = None # If event_id is provided, update the event-specific settings if event_id: # Check if event exists event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # Check if this category is associated with the event association = event_gift_category_crud.get(db, event_id=event_id, category_id=category_id) if not association: # If not associated, create the association association_data = EventGiftCategoryCreate( event_id=event_id, category_id=category_id, display_order=0, # Default display order is_visible=True # Default visibility ) association = event_gift_category_crud.create(db, obj_in=association_data) else: # If display_order or is_visible are in the update data, update the association association_update = {} if hasattr(category_in, 'display_order') and category_in.display_order is not None: association_update['display_order'] = category_in.display_order if hasattr(category_in, 'is_visible') and category_in.is_visible is not None: association_update['is_visible'] = category_in.is_visible if association_update: association = event_gift_category_crud.update( db, db_obj=association, obj_in=association_update ) # Set event-specific properties for the response updated_category.display_order = association.display_order updated_category.is_visible = association.is_visible # Calculate statistics for this event gifts_query = db.query(GiftItem).filter( GiftItem.event_id == event_id, GiftItem.category_id == category_id ) updated_category.total_gifts = gifts_query.count() updated_category.available_gifts = gifts_query.filter( GiftItem.status == GiftStatus.AVAILABLE, GiftItem.is_visible == True ).count() return updated_category @router.delete("/categories/{category_id}", response_model=GiftCategory) def delete_gift_category( *, db: Session = Depends(get_db), category_id: UUID = Path(...), event_id: Optional[UUID] = None, force: bool = False, current_user: User = Depends(get_current_active_user) ) -> Any: """ Delete a gift category. If event_id is provided, only removes the association with that event. If force=True and no event_id is provided, deletes the category completely. """ category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Make a copy of the category for the response category_copy = GiftCategory.model_validate(category) if event_id: # Check if event exists event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # Check if this category is associated with the event association = event_gift_category_crud.get(db, event_id=event_id, category_id=category_id) if not association: raise HTTPException(status_code=404, detail="Category not associated with this event") # Remove the association event_gift_category_crud.remove(db, event_id=event_id, category_id=category_id) # Return the category with event-specific properties set to None category_copy.display_order = None category_copy.is_visible = None category_copy.total_gifts = None category_copy.available_gifts = None return category_copy elif force: # Check if the user has permission to delete the category # This is a more restrictive operation, so we might want to add additional checks # Check if the category is used by any events # Get all associations for this category associations = db.query(EventGiftCategory).filter( EventGiftCategory.category_id == category_id ).all() if associations and len(associations) > 0: # If there are associations, we need to check if the user has permission to manage all events for assoc in associations: event = event_crud.get(db, assoc.event_id) if not event: continue # If the user doesn't have permission for any of the events, deny the operation if event.created_by != current_user.id: raise HTTPException( status_code=403, detail="Not enough permissions. Category is used by events you don't manage." ) # Remove all associations for assoc in associations: event_gift_category_crud.remove(db, event_id=assoc.event_id, category_id=category_id) # Now delete the category itself return gift_category_crud.remove(db, id=category_id) else: # If no event_id and not force, raise an error raise HTTPException( status_code=400, detail="Must provide event_id to remove association or set force=True to delete category completely" ) # ===== EVENT-CATEGORY ASSOCIATIONS ===== # @router.post("/events/{event_id}/categories/{category_id}", response_model=GiftCategory) def associate_category_with_event( *, db: Session = Depends(get_db), event_id: UUID = Path(...), category_id: UUID = Path(...), display_order: int = 0, is_visible: bool = True, current_user: User = Depends(get_current_active_user) ) -> Any: """ Associate an existing category with an event. """ # Check if event exists event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # Check if category exists category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Check if association already exists existing_association = event_gift_category_crud.get(db, event_id=event_id, category_id=category_id) if existing_association: raise HTTPException(status_code=400, detail="Category already associated with this event") # Create the association association_data = EventGiftCategoryCreate( event_id=event_id, category_id=category_id, display_order=display_order, is_visible=is_visible ) event_gift_category_crud.create(db, obj_in=association_data) # Set display properties for the response category.display_order = display_order category.is_visible = is_visible # Calculate statistics for this event gifts_query = db.query(GiftItem).filter( GiftItem.event_id == event_id, GiftItem.category_id == category_id ) category.total_gifts = gifts_query.count() category.available_gifts = gifts_query.filter( GiftItem.status == GiftStatus.AVAILABLE, GiftItem.is_visible == True ).count() return category @router.put("/events/{event_id}/categories/{category_id}", response_model=GiftCategory) def update_category_event_settings( *, db: Session = Depends(get_db), event_id: UUID = Path(...), category_id: UUID = Path(...), display_order: Optional[int] = None, is_visible: Optional[bool] = None, current_user: User = Depends(get_current_active_user) ) -> Any: """ Update the display settings for a category in an event. """ # Check if event exists event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # Check if category exists category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Check if association exists association = event_gift_category_crud.get(db, event_id=event_id, category_id=category_id) if not association: raise HTTPException(status_code=404, detail="Category not associated with this event") # Update the association update_data = {} if display_order is not None: update_data['display_order'] = display_order if is_visible is not None: update_data['is_visible'] = is_visible if update_data: association = event_gift_category_crud.update(db, db_obj=association, obj_in=update_data) # Set display properties for the response category.display_order = association.display_order category.is_visible = association.is_visible # Calculate statistics for this event gifts_query = db.query(GiftItem).filter( GiftItem.event_id == event_id, GiftItem.category_id == category_id ) category.total_gifts = gifts_query.count() category.available_gifts = gifts_query.filter( GiftItem.status == GiftStatus.AVAILABLE, GiftItem.is_visible == True ).count() return category @router.get("/categories/{category_id}/events", response_model=List[Dict[str, Any]]) def get_events_for_category( *, db: Session = Depends(get_db), category_id: UUID = Path(...), current_user: User = Depends(get_current_active_user) ) -> Any: """ Get all events that use a specific category. """ # Check if category exists category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Get all events for this category events = event_gift_category_crud.get_events_by_category(db, category_id=category_id) # Filter events that the user has permission to see result = [] for event in events: # Check if user has permission to see this event if event.created_by == current_user.id or event.is_public: # Get the association to access display_order and is_visible association = event_gift_category_crud.get(db, event_id=event.id, category_id=category_id) if association: # Create a response with event details and association settings event_data = { "event_id": event.id, "event_title": event.title, "event_date": event.event_date, "display_order": association.display_order, "is_visible": association.is_visible } result.append(event_data) return result @router.put("/categories/{category_id}/reorder", response_model=GiftCategory) def reorder_gifts_in_category( *, db: Session = Depends(get_db), category_id: UUID = Path(...), gift_orders: Dict[UUID, int], current_user: User = Depends(get_current_active_user) ) -> Any: """ Reorder gifts within a category. """ category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Check if user has permission to manage this event event = event_crud.get(db, category.event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_category_crud.reorder_gifts(db, category_id=category_id, gift_orders=gift_orders) # ===== GIFT ITEMS ===== # @router.post("/items/", response_model=GiftItem) def create_gift_item( *, db: Session = Depends(get_db), item_in: GiftItemCreate, current_user: User = Depends(get_current_active_user) ) -> Any: """ Create new gift item. """ # Check if user has permission to manage this event event = event_crud.get(db, item_in.event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # If category is specified, check if it exists if item_in.category_id: category = gift_category_crud.get(db, id=item_in.category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Check category belongs to the same event if category.event_id != item_in.event_id: raise HTTPException(status_code=400, detail="Category does not belong to this event") return gift_item_crud.create(db, obj_in=item_in) @router.get("/items/event/{event_id}", response_model=List[GiftItem]) def read_gift_items( *, db: Session = Depends(get_db), event_id: UUID = Path(...), skip: int = 0, limit: int = 100, include_hidden: bool = False, category_id: Optional[UUID] = None, current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Retrieve gift items for an event. """ # Check if event exists and is accessible event = event_crud.get(db, event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # For public access, ensure event is public if not current_user and not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") # If category is specified, check if it exists if category_id: category = gift_category_crud.get(db, id=category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Check category belongs to the requested event if category.event_id != event_id: raise HTTPException(status_code=400, detail="Category does not belong to this event") return gift_item_crud.get_multi_by_event( db, event_id=event_id, skip=skip, limit=limit, include_hidden=include_hidden, category_id=category_id ) @router.get("/items/{item_id}", response_model=GiftItem) def read_gift_item( *, db: Session = Depends(get_db), item_id: UUID = Path(...), current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Get gift item by ID. """ gift = gift_item_crud.get(db, id=item_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if event is public or user is authorized event = event_crud.get(db, gift.event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") if not event.is_public and not current_user: raise HTTPException(status_code=403, detail="Not enough permissions") # Check if gift is visible for public users if not current_user and not gift.is_visible: raise HTTPException(status_code=404, detail="Gift item not found") return gift @router.put("/items/{item_id}", response_model=GiftItem) def update_gift_item( *, db: Session = Depends(get_db), item_id: UUID = Path(...), item_in: GiftItemUpdate, current_user: User = Depends(get_current_active_user) ) -> Any: """ Update a gift item. """ gift = gift_item_crud.get(db, id=item_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if user has permission to manage this event event = event_crud.get(db, gift.event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") # If changing category, check if new category exists and belongs to same event if item_in.category_id and item_in.category_id != gift.category_id: category = gift_category_crud.get(db, id=item_in.category_id) if not category: raise HTTPException(status_code=404, detail="Gift category not found") # Check category belongs to the same event if category.event_id != gift.event_id: raise HTTPException(status_code=400, detail="Category does not belong to this event") return gift_item_crud.update(db, db_obj=gift, obj_in=item_in) @router.delete("/items/{item_id}", response_model=GiftItem) def delete_gift_item( *, db: Session = Depends(get_db), item_id: UUID = Path(...), current_user: User = Depends(get_current_active_user) ) -> Any: """ Delete a gift item. """ gift = gift_item_crud.get(db, id=item_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if user has permission to manage this event event = event_crud.get(db, gift.event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_item_crud.remove(db, id=item_id) @router.put("/items/{item_id}/status", response_model=GiftItem) def update_gift_item_status( *, db: Session = Depends(get_db), item_id: UUID = Path(...), status: GiftStatus, current_user: User = Depends(get_current_active_user) ) -> Any: """ Update a gift item's status. """ gift = gift_item_crud.get(db, id=item_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if user has permission to manage this event event = event_crud.get(db, gift.event_id) if not event: raise HTTPException(status_code=404, detail="Event not found") # Check permissions (basic implementation) if event.created_by != current_user.id: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_item_crud.update_status(db, gift_id=item_id, new_status=status) @router.post("/items/{item_id}/reserve", response_model=GiftItem) def reserve_gift_item( *, db: Session = Depends(get_db), item_id: UUID = Path(...), guest_id: UUID, notes: Optional[str] = None, current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Reserve a gift item for a guest. """ gift = gift_item_crud.get(db, id=item_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if gift is available if gift.status != GiftStatus.AVAILABLE: raise HTTPException(status_code=400, detail="Gift is not available for reservation") # Check if guest exists guest = guest_crud.get(db, id=guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") # Check if guest belongs to the same event if guest.event_id != gift.event_id: raise HTTPException(status_code=400, detail="Guest does not belong to this event") # For admin users, allow direct reservation if current_user: return gift_item_crud.reserve_gift(db, gift_id=item_id, guest_id=guest_id, notes=notes) # For public users, additional validation # Check if event is public event = event_crud.get(db, gift.event_id) if not event or not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_item_crud.reserve_gift(db, gift_id=item_id, guest_id=guest_id, notes=notes) @router.post("/items/{item_id}/cancel-reservation", response_model=GiftItem) def cancel_gift_reservation( *, db: Session = Depends(get_db), item_id: UUID = Path(...), guest_id: UUID, current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Cancel a gift reservation. """ gift = gift_item_crud.get(db, id=item_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if gift is reserved if gift.status != GiftStatus.RESERVED: raise HTTPException(status_code=400, detail="Gift is not currently reserved") # Check if guest exists guest = guest_crud.get(db, id=guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") # For admin users, allow direct cancellation if current_user: return gift_item_crud.cancel_reservation(db, gift_id=item_id, guest_id=guest_id) # ===== GIFT PURCHASES ===== # @router.post("/purchases/", response_model=GiftPurchase) def create_gift_purchase( *, db: Session = Depends(get_db), purchase_in: GiftPurchaseCreate, current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Create a gift purchase record. """ # Check if gift exists gift = gift_item_crud.get(db, id=purchase_in.gift_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # Check if guest exists guest = guest_crud.get(db, id=purchase_in.guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") # Check if guest belongs to the same event as the gift if guest.event_id != gift.event_id: raise HTTPException(status_code=400, detail="Guest does not belong to this event") # For public users, additional validation if not current_user: # Check if event is public event = event_crud.get(db, gift.event_id) if not event or not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_purchase_crud.create(db, obj_in=purchase_in) @router.get("/purchases/{purchase_id}", response_model=GiftPurchase) def read_gift_purchase( *, db: Session = Depends(get_db), purchase_id: UUID = Path(...), current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Get a gift purchase by ID. """ purchase = gift_purchase_crud.get(db, id=purchase_id) if not purchase: raise HTTPException(status_code=404, detail="Gift purchase not found") # If user is authenticated, allow access if current_user: return purchase # For public users, check if the event is public gift = gift_item_crud.get(db, id=purchase.gift_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") event = event_crud.get(db, gift.event_id) if not event or not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") return purchase @router.get("/purchases/gift/{gift_id}", response_model=List[GiftPurchase]) def read_gift_purchases_by_gift( *, db: Session = Depends(get_db), gift_id: UUID = Path(...), current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Get all purchases for a specific gift. """ # Check if gift exists gift = gift_item_crud.get(db, id=gift_id) if not gift: raise HTTPException(status_code=404, detail="Gift item not found") # If user is authenticated, allow access if current_user: return gift_purchase_crud.get_by_gift(db, gift_id=gift_id) # For public users, check if the event is public event = event_crud.get(db, gift.event_id) if not event or not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_purchase_crud.get_by_gift(db, gift_id=gift_id) @router.get("/purchases/guest/{guest_id}", response_model=List[GiftPurchase]) def read_gift_purchases_by_guest( *, db: Session = Depends(get_db), guest_id: UUID = Path(...), current_user: Optional[User] = Depends(get_current_user) ) -> Any: """ Get all purchases made by a specific guest. """ # Check if guest exists guest = guest_crud.get(db, id=guest_id) if not guest: raise HTTPException(status_code=404, detail="Guest not found") # If user is authenticated, allow access if current_user: return gift_purchase_crud.get_by_guest(db, guest_id=guest_id) # For public users, check if the event is public event = event_crud.get(db, guest.event_id) if not event or not event.is_public: raise HTTPException(status_code=403, detail="Not enough permissions") return gift_purchase_crud.get_by_guest(db, guest_id=guest_id)