114 lines
6.5 KiB
Python
114 lines
6.5 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlalchemy.orm import Session
|
|
from sqlalchemy import func
|
|
from ...shared.config.database import get_db
|
|
from ...security.middleware.auth import get_current_user
|
|
from ...auth.models.user import User
|
|
from ...auth.models.role import Role
|
|
from ..models.favorite import Favorite
|
|
from ...rooms.models.room import Room
|
|
from ...rooms.models.room_type import RoomType
|
|
from ..models.review import Review, ReviewStatus
|
|
router = APIRouter(prefix='/favorites', tags=['favorites'])
|
|
|
|
@router.get('/')
|
|
async def get_favorites(current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
|
|
# PERFORMANCE: Use eager-loaded role relationship if available
|
|
if hasattr(current_user, 'role') and current_user.role is not None:
|
|
role_name = current_user.role.name
|
|
else:
|
|
# Fallback: query if relationship wasn't loaded
|
|
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
|
role_name = role.name if role else 'customer'
|
|
|
|
if role_name in ['admin', 'staff', 'accountant']:
|
|
raise HTTPException(status_code=403, detail='Admin, staff, and accountant users cannot have favorites')
|
|
try:
|
|
favorites = db.query(Favorite).filter(Favorite.user_id == current_user.id).order_by(Favorite.created_at.desc()).all()
|
|
result = []
|
|
for favorite in favorites:
|
|
if not favorite.room:
|
|
continue
|
|
room = favorite.room
|
|
review_stats = db.query(func.avg(Review.rating).label('average_rating'), func.count(Review.id).label('total_reviews')).filter(Review.room_id == room.id, Review.status == ReviewStatus.approved).first()
|
|
room_dict = {'id': room.id, 'room_type_id': room.room_type_id, 'room_number': room.room_number, 'floor': room.floor, 'status': room.status.value if hasattr(room.status, 'value') else room.status, 'price': float(room.price) if room.price else 0.0, 'featured': room.featured, 'description': room.description, 'amenities': room.amenities, 'images': room.images or [], 'average_rating': round(float(review_stats.average_rating or 0), 1) if review_stats and review_stats.average_rating else None, 'total_reviews': review_stats.total_reviews or 0 if review_stats else 0}
|
|
if room.room_type:
|
|
room_dict['room_type'] = {'id': room.room_type.id, 'name': room.room_type.name, 'description': room.room_type.description, 'base_price': float(room.room_type.base_price) if room.room_type.base_price else 0.0, 'capacity': room.room_type.capacity, 'amenities': room.room_type.amenities}
|
|
favorite_dict = {'id': favorite.id, 'user_id': favorite.user_id, 'room_id': favorite.room_id, 'room': room_dict, 'created_at': favorite.created_at.isoformat() if favorite.created_at else None}
|
|
result.append(favorite_dict)
|
|
return {'status': 'success', 'data': {'favorites': result, 'total': len(result)}}
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
@router.post('/{room_id}')
|
|
async def add_favorite(room_id: int, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
|
|
# PERFORMANCE: Use eager-loaded role relationship if available
|
|
if hasattr(current_user, 'role') and current_user.role is not None:
|
|
role_name = current_user.role.name
|
|
else:
|
|
# Fallback: query if relationship wasn't loaded
|
|
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
|
role_name = role.name if role else 'customer'
|
|
|
|
if role_name in ['admin', 'staff', 'accountant']:
|
|
raise HTTPException(status_code=403, detail='Admin, staff, and accountant users cannot add favorites')
|
|
try:
|
|
room = db.query(Room).filter(Room.id == room_id).first()
|
|
if not room:
|
|
raise HTTPException(status_code=404, detail='Room not found')
|
|
existing = db.query(Favorite).filter(Favorite.user_id == current_user.id, Favorite.room_id == room_id).first()
|
|
if existing:
|
|
raise HTTPException(status_code=400, detail='Room already in favorites list')
|
|
favorite = Favorite(user_id=current_user.id, room_id=room_id)
|
|
db.add(favorite)
|
|
db.commit()
|
|
db.refresh(favorite)
|
|
return {'status': 'success', 'message': 'Added to favorites list', 'data': {'favorite': favorite}}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
@router.delete('/{room_id}')
|
|
async def remove_favorite(room_id: int, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
|
|
# PERFORMANCE: Use eager-loaded role relationship if available
|
|
if hasattr(current_user, 'role') and current_user.role is not None:
|
|
role_name = current_user.role.name
|
|
else:
|
|
# Fallback: query if relationship wasn't loaded
|
|
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
|
role_name = role.name if role else 'customer'
|
|
|
|
if role_name in ['admin', 'staff', 'accountant']:
|
|
raise HTTPException(status_code=403, detail='Admin, staff, and accountant users cannot remove favorites')
|
|
try:
|
|
favorite = db.query(Favorite).filter(Favorite.user_id == current_user.id, Favorite.room_id == room_id).first()
|
|
if not favorite:
|
|
raise HTTPException(status_code=404, detail='Room not found in favorites list')
|
|
db.delete(favorite)
|
|
db.commit()
|
|
return {'status': 'success', 'message': 'Removed from favorites list'}
|
|
except HTTPException:
|
|
raise
|
|
except Exception as e:
|
|
db.rollback()
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
@router.get('/check/{room_id}')
|
|
async def check_favorite(room_id: int, current_user: User=Depends(get_current_user), db: Session=Depends(get_db)):
|
|
# PERFORMANCE: Use eager-loaded role relationship if available
|
|
if hasattr(current_user, 'role') and current_user.role is not None:
|
|
role_name = current_user.role.name
|
|
else:
|
|
# Fallback: query if relationship wasn't loaded
|
|
role = db.query(Role).filter(Role.id == current_user.role_id).first()
|
|
role_name = role.name if role else 'customer'
|
|
|
|
if role_name in ['admin', 'staff', 'accountant']:
|
|
return {'status': 'success', 'data': {'isFavorited': False}}
|
|
try:
|
|
favorite = db.query(Favorite).filter(Favorite.user_id == current_user.id, Favorite.room_id == room_id).first()
|
|
return {'status': 'success', 'data': {'isFavorited': favorite is not None}}
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e)) |