Spaces:
Sleeping
Sleeping
Upload 162 files
Browse files- src/apis/__pycache__/create_app.cpython-311.pyc +0 -0
- src/apis/controllers/__pycache__/auth_controller.cpython-311.pyc +0 -0
- src/apis/controllers/__pycache__/destination_controller.cpython-311.pyc +0 -0
- src/apis/controllers/__pycache__/post_controller.cpython-311.pyc +0 -0
- src/apis/controllers/admin_controller.py +234 -0
- src/apis/controllers/auth_controller.py +1 -0
- src/apis/controllers/post_controller.py +23 -22
- src/apis/controllers/scheduling_controller.py +30 -28
- src/apis/create_app.py +42 -41
- src/apis/models/__pycache__/destination_models.cpython-311.pyc +0 -0
- src/apis/models/__pycache__/user_models.cpython-311.pyc +0 -0
- src/apis/models/destination_models.py +4 -1
- src/apis/models/user_models.py +3 -0
- src/apis/routes/__pycache__/admin_route.cpython-311.pyc +0 -0
- src/apis/routes/__pycache__/post_router.cpython-311.pyc +0 -0
- src/apis/routes/__pycache__/travel_dest_route.cpython-311.pyc +0 -0
- src/apis/routes/admin_route.py +199 -0
- src/apis/routes/travel_dest_route.py +106 -1
- src/langgraph/multi_agent/chat/__pycache__/chat_flow.cpython-311.pyc +0 -0
- src/langgraph/tools/scheduling_tools.py +7 -1
src/apis/__pycache__/create_app.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/__pycache__/create_app.cpython-311.pyc and b/src/apis/__pycache__/create_app.cpython-311.pyc differ
|
|
|
src/apis/controllers/__pycache__/auth_controller.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/controllers/__pycache__/auth_controller.cpython-311.pyc and b/src/apis/controllers/__pycache__/auth_controller.cpython-311.pyc differ
|
|
|
src/apis/controllers/__pycache__/destination_controller.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/controllers/__pycache__/destination_controller.cpython-311.pyc and b/src/apis/controllers/__pycache__/destination_controller.cpython-311.pyc differ
|
|
|
src/apis/controllers/__pycache__/post_controller.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/controllers/__pycache__/post_controller.cpython-311.pyc and b/src/apis/controllers/__pycache__/post_controller.cpython-311.pyc differ
|
|
|
src/apis/controllers/admin_controller.py
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends, HTTPException, Query
|
| 2 |
+
from typing import Annotated, List
|
| 3 |
+
from fastapi.responses import JSONResponse
|
| 4 |
+
import pandas as pd
|
| 5 |
+
import math
|
| 6 |
+
from src.apis.models.user_models import User
|
| 7 |
+
from src.apis.models.destination_models import Destination
|
| 8 |
+
from src.apis.middlewares.auth_middleware import get_current_user
|
| 9 |
+
from src.utils.logger import logger
|
| 10 |
+
from src.apis.controllers.destination_controller import (
|
| 11 |
+
destination_recommendation_func,
|
| 12 |
+
)
|
| 13 |
+
from fastapi.responses import JSONResponse
|
| 14 |
+
from src.utils.mongo import DestinationCRUD
|
| 15 |
+
from datetime import datetime
|
| 16 |
+
from bson import ObjectId
|
| 17 |
+
|
| 18 |
+
router = APIRouter(prefix="/deadminst", tags=["Destination"])
|
| 19 |
+
|
| 20 |
+
user_dependency = Annotated[User, Depends(get_current_user)]
|
| 21 |
+
EXCEL_FILE_PATH = "./src/data/destination_1_new_tag.xlsx"
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
@router.get("/get_tourist")
|
| 25 |
+
def get_tourist(page: int = Query(default=1, ge=1)):
|
| 26 |
+
try:
|
| 27 |
+
PAGE_SIZE = 10
|
| 28 |
+
df = pd.read_excel(EXCEL_FILE_PATH)
|
| 29 |
+
required_columns = ["name", "description", "image"]
|
| 30 |
+
if not all(col in df.columns for col in required_columns):
|
| 31 |
+
raise HTTPException(
|
| 32 |
+
status_code=400, detail="Missing required columns in Excel file"
|
| 33 |
+
)
|
| 34 |
+
total_items = len(df)
|
| 35 |
+
total_pages = math.ceil(total_items / PAGE_SIZE)
|
| 36 |
+
start_idx = (page - 1) * PAGE_SIZE
|
| 37 |
+
end_idx = start_idx + PAGE_SIZE
|
| 38 |
+
paginated_df = df[required_columns].iloc[start_idx:end_idx]
|
| 39 |
+
tourist_data = paginated_df.to_dict(orient="records")
|
| 40 |
+
return JSONResponse(
|
| 41 |
+
content={
|
| 42 |
+
"data": tourist_data,
|
| 43 |
+
"page": page,
|
| 44 |
+
"total_pages": total_pages,
|
| 45 |
+
"total_items": total_items,
|
| 46 |
+
"page_size": PAGE_SIZE,
|
| 47 |
+
}
|
| 48 |
+
)
|
| 49 |
+
except Exception as e:
|
| 50 |
+
logger.error(f"Error reading the Excel file: {str(e)}")
|
| 51 |
+
raise HTTPException(
|
| 52 |
+
status_code=500, detail=f"Error reading the Excel file: {str(e)}"
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
@router.get("/destination_detail")
|
| 57 |
+
async def get_destinations(destination_id: str = Query(min_length=1, max_length=50)):
|
| 58 |
+
try:
|
| 59 |
+
destination_data = await DestinationCRUD.find_by_id(destination_id)
|
| 60 |
+
if not destination_data:
|
| 61 |
+
return JSONResponse(
|
| 62 |
+
content={"message": "Destination not found"}, status_code=404
|
| 63 |
+
)
|
| 64 |
+
destination_data.pop("created_at")
|
| 65 |
+
destination_data.pop("updated_at")
|
| 66 |
+
destination_data.pop("expire_at")
|
| 67 |
+
destination_data["id"] = str(destination_data["_id"])
|
| 68 |
+
destination_data.pop("_id")
|
| 69 |
+
print("destination_data", destination_data)
|
| 70 |
+
return JSONResponse(content=destination_data, status_code=200)
|
| 71 |
+
|
| 72 |
+
except Exception as e:
|
| 73 |
+
logger.error(f"Error fetching destination: {str(e)}")
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
@router.get("/paginate")
|
| 77 |
+
async def get_paginated_destinations(
|
| 78 |
+
page: int = Query(default=1, ge=1), page_size: int = Query(default=10, ge=1, le=100)
|
| 79 |
+
):
|
| 80 |
+
"""
|
| 81 |
+
Get paginated destinations from database
|
| 82 |
+
|
| 83 |
+
Args:
|
| 84 |
+
page: Page number (starts from 1)
|
| 85 |
+
page_size: Number of items per page
|
| 86 |
+
|
| 87 |
+
Returns:
|
| 88 |
+
Paginated list of destinations with pagination metadata
|
| 89 |
+
"""
|
| 90 |
+
try:
|
| 91 |
+
# Calculate skip value for pagination
|
| 92 |
+
skip = (page - 1) * page_size
|
| 93 |
+
|
| 94 |
+
# Query destinations with pagination
|
| 95 |
+
destination_data = await DestinationCRUD.find_many(
|
| 96 |
+
filter={}, # Empty filter means get all
|
| 97 |
+
skip=skip,
|
| 98 |
+
limit=page_size,
|
| 99 |
+
sort=[("created_at", -1)], # Sort by created_at descending
|
| 100 |
+
)
|
| 101 |
+
|
| 102 |
+
# Get total count for pagination metadata
|
| 103 |
+
total_items = await DestinationCRUD.count({})
|
| 104 |
+
total_pages = math.ceil(total_items / page_size)
|
| 105 |
+
|
| 106 |
+
# Process results
|
| 107 |
+
serialized_data = []
|
| 108 |
+
for dest in destination_data:
|
| 109 |
+
dest.pop("created_at")
|
| 110 |
+
dest.pop("updated_at")
|
| 111 |
+
dest.pop("expire_at")
|
| 112 |
+
|
| 113 |
+
dest_dict = {
|
| 114 |
+
"id": dest["_id"],
|
| 115 |
+
**{k: v for k, v in dest.items() if k != "_id"},
|
| 116 |
+
}
|
| 117 |
+
serialized_data.append(dest_dict)
|
| 118 |
+
|
| 119 |
+
return JSONResponse(
|
| 120 |
+
content={
|
| 121 |
+
"data": serialized_data,
|
| 122 |
+
"page": page,
|
| 123 |
+
"total_pages": total_pages,
|
| 124 |
+
"total_items": total_items,
|
| 125 |
+
"page_size": page_size,
|
| 126 |
+
},
|
| 127 |
+
status_code=200,
|
| 128 |
+
)
|
| 129 |
+
except Exception as e:
|
| 130 |
+
logger.error(f"Error fetching paginated destinations: {str(e)}")
|
| 131 |
+
raise HTTPException(
|
| 132 |
+
status_code=500, detail=f"Error fetching paginated destinations: {str(e)}"
|
| 133 |
+
)
|
| 134 |
+
|
| 135 |
+
@router.post("/")
|
| 136 |
+
async def create_destination(
|
| 137 |
+
destination_data: Destination, current_user: user_dependency
|
| 138 |
+
):
|
| 139 |
+
if current_user["role"] != "admin":
|
| 140 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 141 |
+
try:
|
| 142 |
+
destination_id = await DestinationCRUD.create(destination_data.model_dump())
|
| 143 |
+
|
| 144 |
+
if not destination_id:
|
| 145 |
+
raise HTTPException(status_code=400, detail="Failed to create destination")
|
| 146 |
+
|
| 147 |
+
return JSONResponse(
|
| 148 |
+
content={
|
| 149 |
+
"message": "Destination created successfully",
|
| 150 |
+
"id": destination_id,
|
| 151 |
+
},
|
| 152 |
+
status_code=201,
|
| 153 |
+
)
|
| 154 |
+
except Exception as e:
|
| 155 |
+
logger.error(f"Error creating destination: {str(e)}")
|
| 156 |
+
raise HTTPException(
|
| 157 |
+
status_code=500, detail=f"Error creating destination: {str(e)}"
|
| 158 |
+
)
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
@router.put("/{destination_id}")
|
| 162 |
+
async def update_destination(
|
| 163 |
+
destination_id: str, destination_data: dict, current_user: user_dependency
|
| 164 |
+
):
|
| 165 |
+
if current_user["role"] != "admin":
|
| 166 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 167 |
+
try:
|
| 168 |
+
# Add updated_at timestamp
|
| 169 |
+
destination_data["updated_at"] = datetime.utcnow()
|
| 170 |
+
|
| 171 |
+
# Update destination
|
| 172 |
+
result = await DestinationCRUD.update(
|
| 173 |
+
{"_id": ObjectId(destination_id)}, destination_data
|
| 174 |
+
)
|
| 175 |
+
|
| 176 |
+
if not result:
|
| 177 |
+
raise HTTPException(status_code=404, detail="Destination not found")
|
| 178 |
+
|
| 179 |
+
return JSONResponse(
|
| 180 |
+
content={"message": "Destination updated successfully"}, status_code=200
|
| 181 |
+
)
|
| 182 |
+
except Exception as e:
|
| 183 |
+
logger.error(f"Error updating destination: {str(e)}")
|
| 184 |
+
raise HTTPException(
|
| 185 |
+
status_code=500, detail=f"Error updating destination: {str(e)}"
|
| 186 |
+
)
|
| 187 |
+
|
| 188 |
+
|
| 189 |
+
@router.delete("/{destination_id}")
|
| 190 |
+
async def delete_destination(destination_id: str, current_user: user_dependency):
|
| 191 |
+
if current_user["role"] != "admin":
|
| 192 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 193 |
+
try:
|
| 194 |
+
# Delete destination
|
| 195 |
+
result = await DestinationCRUD.delete_one({"_id": ObjectId(destination_id)})
|
| 196 |
+
|
| 197 |
+
if not result:
|
| 198 |
+
raise HTTPException(status_code=404, detail="Destination not found")
|
| 199 |
+
|
| 200 |
+
return JSONResponse(
|
| 201 |
+
content={"message": "Destination deleted successfully"}, status_code=200
|
| 202 |
+
)
|
| 203 |
+
except Exception as e:
|
| 204 |
+
logger.error(f"Error deleting destination: {str(e)}")
|
| 205 |
+
raise HTTPException(
|
| 206 |
+
status_code=500, detail=f"Error deleting destination: {str(e)}"
|
| 207 |
+
)
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
@router.get("/")
|
| 211 |
+
async def get_all_destinations(current_user: user_dependency):
|
| 212 |
+
print("current_user", current_user)
|
| 213 |
+
if current_user["role"] != "admin":
|
| 214 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 215 |
+
try:
|
| 216 |
+
# Get all destinations
|
| 217 |
+
destinations = await DestinationCRUD.find_all()
|
| 218 |
+
|
| 219 |
+
# Process results
|
| 220 |
+
serialized_data = []
|
| 221 |
+
for dest in destinations:
|
| 222 |
+
dest.pop("created_at")
|
| 223 |
+
dest.pop("updated_at")
|
| 224 |
+
dest.pop("expire_at")
|
| 225 |
+
dest["id"] = str(dest["_id"])
|
| 226 |
+
dest.pop("_id")
|
| 227 |
+
serialized_data.append(dest)
|
| 228 |
+
|
| 229 |
+
return JSONResponse(content={"data": serialized_data}, status_code=200)
|
| 230 |
+
except Exception as e:
|
| 231 |
+
logger.error(f"Error fetching destinations: {str(e)}")
|
| 232 |
+
raise HTTPException(
|
| 233 |
+
status_code=500, detail=f"Error fetching destinations: {str(e)}"
|
| 234 |
+
)
|
src/apis/controllers/auth_controller.py
CHANGED
|
@@ -35,6 +35,7 @@ async def login_control(token):
|
|
| 35 |
token = jwt_provider.encrypt({"id": str(user_id)})
|
| 36 |
user_data = user.__dict__
|
| 37 |
user_data["id"] = user_id
|
|
|
|
| 38 |
user_data.pop("created_at", None)
|
| 39 |
user_data.pop("updated_at", None)
|
| 40 |
user_data.pop("expire_at", None)
|
|
|
|
| 35 |
token = jwt_provider.encrypt({"id": str(user_id)})
|
| 36 |
user_data = user.__dict__
|
| 37 |
user_data["id"] = user_id
|
| 38 |
+
user_data["role"] = existing_user["role"]
|
| 39 |
user_data.pop("created_at", None)
|
| 40 |
user_data.pop("updated_at", None)
|
| 41 |
user_data.pop("expire_at", None)
|
src/apis/controllers/post_controller.py
CHANGED
|
@@ -12,28 +12,29 @@ import math
|
|
| 12 |
async def create_a_post_controller(
|
| 13 |
content: str, user_id: str, destination_id: str, images: list
|
| 14 |
) -> Dict:
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
|
|
|
| 37 |
|
| 38 |
|
| 39 |
async def get_a_post_controller(post_id: str) -> Dict:
|
|
|
|
| 12 |
async def create_a_post_controller(
|
| 13 |
content: str, user_id: str, destination_id: str, images: list
|
| 14 |
) -> Dict:
|
| 15 |
+
try:
|
| 16 |
+
image_url = await call_external_api(
|
| 17 |
+
method="POST",
|
| 18 |
+
# url="http://localhost:8000/upload_image",
|
| 19 |
+
# url="https://abao77-image-retrieval.hf.space/upload_image",
|
| 20 |
+
url="https://abao77-image-retrieval-full.hf.space/upload_image",
|
| 21 |
+
json={"base64_image": images},
|
| 22 |
+
)
|
| 23 |
+
print(f"IMAGE URL: {image_url}")
|
| 24 |
+
post = {
|
| 25 |
+
"content": content,
|
| 26 |
+
"user_id": user_id,
|
| 27 |
+
"destination_id": destination_id,
|
| 28 |
+
"comment_count": 0,
|
| 29 |
+
"reaction_count": 0,
|
| 30 |
+
"picture": image_url["public_url"] if image_url.get("public_url") else None,
|
| 31 |
+
"like": [],
|
| 32 |
+
}
|
| 33 |
+
await PostCRUD.create(post)
|
| 34 |
+
return {"status": "success", "message": "Post created successfully"}
|
| 35 |
+
except Exception as e:
|
| 36 |
+
logger.error(f"Error creating post: {str(e)}")
|
| 37 |
+
return {"status": "error", "message": str(e)}
|
| 38 |
|
| 39 |
|
| 40 |
async def get_a_post_controller(post_id: str) -> Dict:
|
src/apis/controllers/scheduling_controller.py
CHANGED
|
@@ -12,36 +12,38 @@ async def create_a_activity_controller(
|
|
| 12 |
start_time: datetime,
|
| 13 |
end_time: datetime,
|
| 14 |
user_id: str,
|
|
|
|
| 15 |
) -> Dict[str, str]:
|
| 16 |
try:
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
|
| 21 |
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
| 44 |
-
|
|
|
|
| 45 |
document = {
|
| 46 |
"user_id": user_id,
|
| 47 |
"activity_category": activity_category,
|
|
|
|
| 12 |
start_time: datetime,
|
| 13 |
end_time: datetime,
|
| 14 |
user_id: str,
|
| 15 |
+
overlap_allow: bool = True,
|
| 16 |
) -> Dict[str, str]:
|
| 17 |
try:
|
| 18 |
+
if not overlap_allow:
|
| 19 |
+
existing_activity = await ScheduleCRUD.read_one(
|
| 20 |
+
{
|
| 21 |
+
"user_id": user_id,
|
| 22 |
+
"$or": [
|
| 23 |
+
{
|
| 24 |
+
"start_time": {"$lte": start_time},
|
| 25 |
+
"end_time": {"$gt": start_time},
|
| 26 |
+
},
|
| 27 |
+
{
|
| 28 |
+
"start_time": {"$lt": end_time},
|
| 29 |
+
"end_time": {"$gte": end_time},
|
| 30 |
+
},
|
| 31 |
+
{
|
| 32 |
+
"start_time": {"$gte": start_time},
|
| 33 |
+
"end_time": {"$lte": end_time},
|
| 34 |
+
},
|
| 35 |
+
],
|
| 36 |
+
}
|
| 37 |
+
)
|
| 38 |
+
if existing_activity:
|
| 39 |
+
activity_category = existing_activity.get("activity_category", "N/A")
|
| 40 |
+
description = existing_activity.get("description", "N/A")
|
| 41 |
+
start_time = existing_activity.get("start_time", "N/A")
|
| 42 |
+
end_time = existing_activity.get("end_time", "N/A")
|
| 43 |
+
return {
|
| 44 |
+
"status": "error",
|
| 45 |
+
"message": f"""Overlapping activities found:\nDescription: {description}, \nCategory: {activity_category}, \nStart time: {start_time}, \nEnd time: {end_time}. Please update or delete the existing activity to create a new one.""",
|
| 46 |
+
}
|
| 47 |
document = {
|
| 48 |
"user_id": user_id,
|
| 49 |
"activity_category": activity_category,
|
src/apis/create_app.py
CHANGED
|
@@ -1,41 +1,42 @@
|
|
| 1 |
-
from fastapi import FastAPI, APIRouter
|
| 2 |
-
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
-
from src.apis.routes.chat_route import router as router_chat
|
| 4 |
-
from src.apis.routes.auth_route import router as router_auth
|
| 5 |
-
from src.apis.routes.location_route import router as router_location
|
| 6 |
-
from src.apis.routes.hotel_route import router as router_hotel
|
| 7 |
-
from src.apis.routes.travel_dest_route import router as router_travel_dest
|
| 8 |
-
from src.apis.routes.scheduling_router import router as router_scheduling
|
| 9 |
-
from src.apis.routes.planner_route import router as router_planner
|
| 10 |
-
from src.apis.routes.post_router import router as router_post
|
| 11 |
-
from src.apis.routes.comment_route import router as router_comment
|
| 12 |
-
from src.apis.routes.reaction_route import router as router_reaction
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
api_router
|
| 16 |
-
api_router.include_router(
|
| 17 |
-
api_router.include_router(
|
| 18 |
-
api_router.include_router(
|
| 19 |
-
api_router.include_router(
|
| 20 |
-
api_router.include_router(
|
| 21 |
-
api_router.include_router(
|
| 22 |
-
api_router.include_router(
|
| 23 |
-
api_router.include_router(
|
| 24 |
-
api_router.include_router(
|
| 25 |
-
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
| 36 |
-
|
| 37 |
-
|
| 38 |
-
|
| 39 |
-
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, APIRouter
|
| 2 |
+
from fastapi.middleware.cors import CORSMiddleware
|
| 3 |
+
from src.apis.routes.chat_route import router as router_chat
|
| 4 |
+
from src.apis.routes.auth_route import router as router_auth
|
| 5 |
+
from src.apis.routes.location_route import router as router_location
|
| 6 |
+
from src.apis.routes.hotel_route import router as router_hotel
|
| 7 |
+
from src.apis.routes.travel_dest_route import router as router_travel_dest
|
| 8 |
+
from src.apis.routes.scheduling_router import router as router_scheduling
|
| 9 |
+
from src.apis.routes.planner_route import router as router_planner
|
| 10 |
+
from src.apis.routes.post_router import router as router_post
|
| 11 |
+
from src.apis.routes.comment_route import router as router_comment
|
| 12 |
+
from src.apis.routes.reaction_route import router as router_reaction
|
| 13 |
+
from src.apis.routes.admin_route import router as router_admin
|
| 14 |
+
|
| 15 |
+
api_router = APIRouter()
|
| 16 |
+
api_router.include_router(router_chat)
|
| 17 |
+
api_router.include_router(router_auth)
|
| 18 |
+
api_router.include_router(router_location)
|
| 19 |
+
api_router.include_router(router_hotel)
|
| 20 |
+
api_router.include_router(router_travel_dest)
|
| 21 |
+
api_router.include_router(router_scheduling)
|
| 22 |
+
api_router.include_router(router_planner)
|
| 23 |
+
api_router.include_router(router_post)
|
| 24 |
+
api_router.include_router(router_comment)
|
| 25 |
+
api_router.include_router(router_reaction)
|
| 26 |
+
api_router.include_router(router_admin)
|
| 27 |
+
|
| 28 |
+
def create_app():
|
| 29 |
+
app = FastAPI(
|
| 30 |
+
docs_url="/",
|
| 31 |
+
title="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjY3ZTU1ZTczYTA0MzI1YmUzNjAzYjU2MCJ9.Vdz3DdbvNUdUERDXEOyvi14EuYATRw29eOVWNGTQIYo"
|
| 32 |
+
)
|
| 33 |
+
|
| 34 |
+
app.add_middleware(
|
| 35 |
+
CORSMiddleware,
|
| 36 |
+
allow_origins=["*"],
|
| 37 |
+
allow_credentials=True,
|
| 38 |
+
allow_methods=["*"],
|
| 39 |
+
allow_headers=["*"],
|
| 40 |
+
)
|
| 41 |
+
|
| 42 |
+
return app
|
src/apis/models/__pycache__/destination_models.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/models/__pycache__/destination_models.cpython-311.pyc and b/src/apis/models/__pycache__/destination_models.cpython-311.pyc differ
|
|
|
src/apis/models/__pycache__/user_models.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/models/__pycache__/user_models.cpython-311.pyc and b/src/apis/models/__pycache__/user_models.cpython-311.pyc differ
|
|
|
src/apis/models/destination_models.py
CHANGED
|
@@ -8,13 +8,16 @@ class Destination(BaseDocument):
|
|
| 8 |
name: str = Field("", description="Destination's name")
|
| 9 |
description: str = Field("", description="Destination's description")
|
| 10 |
image: str = Field("", description="Destination's picture")
|
| 11 |
-
|
|
|
|
| 12 |
model_config = {
|
| 13 |
"json_schema_extra": {
|
| 14 |
"example": {
|
| 15 |
"name": "Hanoi",
|
| 16 |
"description": "Hanoi is the capital of Vietnam",
|
| 17 |
"image": "https://www.google.com.vn",
|
|
|
|
|
|
|
| 18 |
}
|
| 19 |
}
|
| 20 |
}
|
|
|
|
| 8 |
name: str = Field("", description="Destination's name")
|
| 9 |
description: str = Field("", description="Destination's description")
|
| 10 |
image: str = Field("", description="Destination's picture")
|
| 11 |
+
created_user_id: str = Field("", description="Destination's created user")
|
| 12 |
+
updated_user_id: str = Field("", description="Destination's updated user")
|
| 13 |
model_config = {
|
| 14 |
"json_schema_extra": {
|
| 15 |
"example": {
|
| 16 |
"name": "Hanoi",
|
| 17 |
"description": "Hanoi is the capital of Vietnam",
|
| 18 |
"image": "https://www.google.com.vn",
|
| 19 |
+
"created_user_id": "1234567890",
|
| 20 |
+
"updated_user_id": "1234567890",
|
| 21 |
}
|
| 22 |
}
|
| 23 |
}
|
src/apis/models/user_models.py
CHANGED
|
@@ -10,6 +10,7 @@ def get_user(user) -> dict:
|
|
| 10 |
"email": user["email"],
|
| 11 |
"picture": user["picture"],
|
| 12 |
"contact_number": user["contact_number"],
|
|
|
|
| 13 |
}
|
| 14 |
|
| 15 |
|
|
@@ -23,6 +24,7 @@ class User(BaseDocument):
|
|
| 23 |
email: EmailStr = Field("", description="User's email")
|
| 24 |
picture: str = Field("", title="User Picture")
|
| 25 |
contact_number: str = Field("", description="User's contact number")
|
|
|
|
| 26 |
|
| 27 |
class Config:
|
| 28 |
json_schema_extra = {
|
|
@@ -31,5 +33,6 @@ class User(BaseDocument):
|
|
| 31 |
"email": "johnUS192@gmail.com",
|
| 32 |
"picture": "https://example.com/picture.jpg",
|
| 33 |
"contact_number": "1234567890",
|
|
|
|
| 34 |
}
|
| 35 |
}
|
|
|
|
| 10 |
"email": user["email"],
|
| 11 |
"picture": user["picture"],
|
| 12 |
"contact_number": user["contact_number"],
|
| 13 |
+
"role": user["role"],
|
| 14 |
}
|
| 15 |
|
| 16 |
|
|
|
|
| 24 |
email: EmailStr = Field("", description="User's email")
|
| 25 |
picture: str = Field("", title="User Picture")
|
| 26 |
contact_number: str = Field("", description="User's contact number")
|
| 27 |
+
role: str = Field("", description="User's role")
|
| 28 |
|
| 29 |
class Config:
|
| 30 |
json_schema_extra = {
|
|
|
|
| 33 |
"email": "johnUS192@gmail.com",
|
| 34 |
"picture": "https://example.com/picture.jpg",
|
| 35 |
"contact_number": "1234567890",
|
| 36 |
+
"role": "user",
|
| 37 |
}
|
| 38 |
}
|
src/apis/routes/__pycache__/admin_route.cpython-311.pyc
ADDED
|
Binary file (10.8 kB). View file
|
|
|
src/apis/routes/__pycache__/post_router.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/routes/__pycache__/post_router.cpython-311.pyc and b/src/apis/routes/__pycache__/post_router.cpython-311.pyc differ
|
|
|
src/apis/routes/__pycache__/travel_dest_route.cpython-311.pyc
CHANGED
|
Binary files a/src/apis/routes/__pycache__/travel_dest_route.cpython-311.pyc and b/src/apis/routes/__pycache__/travel_dest_route.cpython-311.pyc differ
|
|
|
src/apis/routes/admin_route.py
ADDED
|
@@ -0,0 +1,199 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import APIRouter, Depends, HTTPException, Query
|
| 2 |
+
from typing import Annotated, List
|
| 3 |
+
from fastapi.responses import JSONResponse
|
| 4 |
+
import pandas as pd
|
| 5 |
+
import math
|
| 6 |
+
from src.apis.models.user_models import User
|
| 7 |
+
from src.apis.models.destination_models import Destination
|
| 8 |
+
from src.apis.middlewares.auth_middleware import get_current_user
|
| 9 |
+
from src.utils.logger import logger
|
| 10 |
+
from fastapi import status
|
| 11 |
+
from src.utils.mongo import DestinationCRUD, PostCRUD, UserCRUD
|
| 12 |
+
from datetime import datetime
|
| 13 |
+
from bson import ObjectId
|
| 14 |
+
|
| 15 |
+
router = APIRouter(prefix="/admin", tags=["Admin"])
|
| 16 |
+
|
| 17 |
+
user_dependency = Annotated[User, Depends(get_current_user)]
|
| 18 |
+
|
| 19 |
+
@router.get("/destination/paginate")
|
| 20 |
+
async def get_paginated_destinations(
|
| 21 |
+
user: user_dependency,
|
| 22 |
+
page: int = Query(default=1, ge=1),
|
| 23 |
+
page_size: int = Query(default=10, ge=1, le=100)
|
| 24 |
+
):
|
| 25 |
+
"""
|
| 26 |
+
Get paginated destinations from database
|
| 27 |
+
|
| 28 |
+
Args:
|
| 29 |
+
page: Page number (starts from 1)
|
| 30 |
+
page_size: Number of items per page
|
| 31 |
+
|
| 32 |
+
Returns:
|
| 33 |
+
Paginated list of destinations with pagination metadata
|
| 34 |
+
"""
|
| 35 |
+
if user["role"] != "admin":
|
| 36 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 37 |
+
try:
|
| 38 |
+
# Calculate skip value for pagination
|
| 39 |
+
skip = (page - 1) * page_size
|
| 40 |
+
|
| 41 |
+
# Query destinations with pagination
|
| 42 |
+
destination_data = await DestinationCRUD.find_many(
|
| 43 |
+
filter={}, # Empty filter means get all
|
| 44 |
+
skip=skip,
|
| 45 |
+
limit=page_size,
|
| 46 |
+
sort=[("created_at", -1)], # Sort by created_at descending
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
# Get total count for pagination metadata
|
| 50 |
+
total_items = await DestinationCRUD.count({})
|
| 51 |
+
total_pages = math.ceil(total_items / page_size)
|
| 52 |
+
|
| 53 |
+
# Collect unique user IDs
|
| 54 |
+
user_ids = set()
|
| 55 |
+
for dest in destination_data:
|
| 56 |
+
if dest.get("created_user_id"):
|
| 57 |
+
user_ids.add(dest["created_user_id"])
|
| 58 |
+
if dest.get("updated_user_id"):
|
| 59 |
+
user_ids.add(dest["updated_user_id"])
|
| 60 |
+
|
| 61 |
+
# Fetch all users in a single query
|
| 62 |
+
users = {}
|
| 63 |
+
if user_ids:
|
| 64 |
+
user_data = await UserCRUD.find_many(
|
| 65 |
+
filter={"_id": {"$in": [ObjectId(uid) for uid in user_ids]}}
|
| 66 |
+
)
|
| 67 |
+
users = {str(user["_id"]): user for user in user_data}
|
| 68 |
+
|
| 69 |
+
# Process results
|
| 70 |
+
serialized_data = []
|
| 71 |
+
for dest in destination_data:
|
| 72 |
+
# Convert timestamps to ISO format
|
| 73 |
+
if "created_at" in dest:
|
| 74 |
+
dest["created_at"] = dest["created_at"].isoformat() if dest["created_at"] else None
|
| 75 |
+
if "updated_at" in dest:
|
| 76 |
+
dest["updated_at"] = dest["updated_at"].isoformat() if dest["updated_at"] else None
|
| 77 |
+
dest.pop("expire_at", None)
|
| 78 |
+
|
| 79 |
+
dest_dict = {
|
| 80 |
+
"id": dest["_id"],
|
| 81 |
+
"created_user": {
|
| 82 |
+
"id": dest.get("created_user_id"),
|
| 83 |
+
"name": users.get(dest.get("created_user_id", ""), {}).get("name"),
|
| 84 |
+
"email": users.get(dest.get("created_user_id", ""), {}).get("email")
|
| 85 |
+
} if dest.get("created_user_id") else None,
|
| 86 |
+
"updated_user": {
|
| 87 |
+
"id": dest.get("updated_user_id"),
|
| 88 |
+
"name": users.get(dest.get("updated_user_id", ""), {}).get("name"),
|
| 89 |
+
"email": users.get(dest.get("updated_user_id", ""), {}).get("email")
|
| 90 |
+
} if dest.get("updated_user_id") else None,
|
| 91 |
+
**{k: v for k, v in dest.items() if k not in ["_id", "created_user_id", "updated_user_id"]},
|
| 92 |
+
}
|
| 93 |
+
serialized_data.append(dest_dict)
|
| 94 |
+
|
| 95 |
+
return JSONResponse(
|
| 96 |
+
content={
|
| 97 |
+
"data": serialized_data,
|
| 98 |
+
"page": page,
|
| 99 |
+
"total_pages": total_pages,
|
| 100 |
+
"total_items": total_items,
|
| 101 |
+
"page_size": page_size,
|
| 102 |
+
},
|
| 103 |
+
status_code=200,
|
| 104 |
+
)
|
| 105 |
+
except Exception as e:
|
| 106 |
+
logger.error(f"Error fetching paginated destinations: {str(e)}")
|
| 107 |
+
raise HTTPException(
|
| 108 |
+
status_code=500, detail=f"Error fetching paginated destinations: {str(e)}"
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
@router.post("/destination")
|
| 114 |
+
async def create_destination(
|
| 115 |
+
destination_data: Destination, current_user: user_dependency
|
| 116 |
+
):
|
| 117 |
+
if current_user["role"] != "admin":
|
| 118 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 119 |
+
try:
|
| 120 |
+
destination_data.created_user_id = current_user["id"]
|
| 121 |
+
destination_data.updated_user_id = current_user["id"]
|
| 122 |
+
destination_id = await DestinationCRUD.create(destination_data.model_dump())
|
| 123 |
+
|
| 124 |
+
if not destination_id:
|
| 125 |
+
raise HTTPException(status_code=400, detail="Failed to create destination")
|
| 126 |
+
|
| 127 |
+
return JSONResponse(
|
| 128 |
+
content={
|
| 129 |
+
"message": "Destination created successfully",
|
| 130 |
+
"id": destination_id,
|
| 131 |
+
},
|
| 132 |
+
status_code=201,
|
| 133 |
+
)
|
| 134 |
+
except Exception as e:
|
| 135 |
+
logger.error(f"Error creating destination: {str(e)}")
|
| 136 |
+
raise HTTPException(
|
| 137 |
+
status_code=500, detail=f"Error creating destination: {str(e)}"
|
| 138 |
+
)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
@router.put("/destination/{destination_id}")
|
| 142 |
+
async def update_destination(
|
| 143 |
+
destination_id: str, destination_data: dict, current_user: user_dependency
|
| 144 |
+
):
|
| 145 |
+
if current_user["role"] != "admin":
|
| 146 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 147 |
+
try:
|
| 148 |
+
# Add updated_at timestamp
|
| 149 |
+
destination_data["updated_at"] = datetime.utcnow()
|
| 150 |
+
destination_data["updated_user_id"] = current_user["id"]
|
| 151 |
+
# Update destination
|
| 152 |
+
result = await DestinationCRUD.update(
|
| 153 |
+
{"_id": ObjectId(destination_id)}, destination_data
|
| 154 |
+
)
|
| 155 |
+
|
| 156 |
+
if not result:
|
| 157 |
+
raise HTTPException(status_code=404, detail="Destination not found")
|
| 158 |
+
|
| 159 |
+
return JSONResponse(
|
| 160 |
+
content={"message": "Destination updated successfully"}, status_code=200
|
| 161 |
+
)
|
| 162 |
+
except Exception as e:
|
| 163 |
+
logger.error(f"Error updating destination: {str(e)}")
|
| 164 |
+
raise HTTPException(
|
| 165 |
+
status_code=500, detail=f"Error updating destination: {str(e)}"
|
| 166 |
+
)
|
| 167 |
+
|
| 168 |
+
|
| 169 |
+
@router.delete("/destination/{destination_id}")
|
| 170 |
+
async def delete_destination(destination_id: str, current_user: user_dependency):
|
| 171 |
+
print("destination_id", destination_id)
|
| 172 |
+
if current_user["role"] != "admin":
|
| 173 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 174 |
+
try:
|
| 175 |
+
# Delete destination
|
| 176 |
+
result = await DestinationCRUD.delete_one({"_id": ObjectId(destination_id)})
|
| 177 |
+
|
| 178 |
+
if not result:
|
| 179 |
+
raise HTTPException(status_code=404, detail="Destination not found")
|
| 180 |
+
|
| 181 |
+
return JSONResponse(
|
| 182 |
+
content={"message": "Destination deleted successfully"}, status_code=200
|
| 183 |
+
)
|
| 184 |
+
except Exception as e:
|
| 185 |
+
logger.error(f"Error deleting destination: {str(e)}")
|
| 186 |
+
raise HTTPException(
|
| 187 |
+
status_code=500, detail=f"Error deleting destination: {str(e)}"
|
| 188 |
+
)
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
|
| 192 |
+
@router.delete("/post/delete/{post_id}", status_code=status.HTTP_200_OK)
|
| 193 |
+
async def delete_post(post_id: str, user: user_dependency):
|
| 194 |
+
if user["role"] != "admin":
|
| 195 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 196 |
+
result = await PostCRUD.delete_one({"_id": ObjectId(post_id)})
|
| 197 |
+
if not result:
|
| 198 |
+
raise HTTPException(status_code=404, detail="Post not found")
|
| 199 |
+
return JSONResponse(content={"message": "Post deleted successfully"}, status_code=200)
|
src/apis/routes/travel_dest_route.py
CHANGED
|
@@ -1,9 +1,10 @@
|
|
| 1 |
from fastapi import APIRouter, Depends, HTTPException, Query
|
| 2 |
-
from typing import Annotated
|
| 3 |
from fastapi.responses import JSONResponse
|
| 4 |
import pandas as pd
|
| 5 |
import math
|
| 6 |
from src.apis.models.user_models import User
|
|
|
|
| 7 |
from src.apis.middlewares.auth_middleware import get_current_user
|
| 8 |
from src.utils.logger import logger
|
| 9 |
from src.apis.controllers.destination_controller import (
|
|
@@ -11,6 +12,8 @@ from src.apis.controllers.destination_controller import (
|
|
| 11 |
)
|
| 12 |
from fastapi.responses import JSONResponse
|
| 13 |
from src.utils.mongo import DestinationCRUD
|
|
|
|
|
|
|
| 14 |
|
| 15 |
router = APIRouter(prefix="/dest", tags=["Destination"])
|
| 16 |
|
|
@@ -153,3 +156,105 @@ async def get_tourist_names():
|
|
| 153 |
@router.get("/suggest")
|
| 154 |
async def destination_suggestion(question: str, top_k: int = Query(default=5, ge=1)):
|
| 155 |
return JSONResponse(await destination_recommendation_func(question))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
from fastapi import APIRouter, Depends, HTTPException, Query
|
| 2 |
+
from typing import Annotated, List
|
| 3 |
from fastapi.responses import JSONResponse
|
| 4 |
import pandas as pd
|
| 5 |
import math
|
| 6 |
from src.apis.models.user_models import User
|
| 7 |
+
from src.apis.models.destination_models import Destination
|
| 8 |
from src.apis.middlewares.auth_middleware import get_current_user
|
| 9 |
from src.utils.logger import logger
|
| 10 |
from src.apis.controllers.destination_controller import (
|
|
|
|
| 12 |
)
|
| 13 |
from fastapi.responses import JSONResponse
|
| 14 |
from src.utils.mongo import DestinationCRUD
|
| 15 |
+
from datetime import datetime
|
| 16 |
+
from bson import ObjectId
|
| 17 |
|
| 18 |
router = APIRouter(prefix="/dest", tags=["Destination"])
|
| 19 |
|
|
|
|
| 156 |
@router.get("/suggest")
|
| 157 |
async def destination_suggestion(question: str, top_k: int = Query(default=5, ge=1)):
|
| 158 |
return JSONResponse(await destination_recommendation_func(question))
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
@router.post("/")
|
| 162 |
+
async def create_destination(
|
| 163 |
+
destination_data: Destination, current_user: user_dependency
|
| 164 |
+
):
|
| 165 |
+
if current_user["role"] != "admin":
|
| 166 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 167 |
+
try:
|
| 168 |
+
destination_id = await DestinationCRUD.create(destination_data.model_dump())
|
| 169 |
+
|
| 170 |
+
if not destination_id:
|
| 171 |
+
raise HTTPException(status_code=400, detail="Failed to create destination")
|
| 172 |
+
|
| 173 |
+
return JSONResponse(
|
| 174 |
+
content={
|
| 175 |
+
"message": "Destination created successfully",
|
| 176 |
+
"id": destination_id,
|
| 177 |
+
},
|
| 178 |
+
status_code=201,
|
| 179 |
+
)
|
| 180 |
+
except Exception as e:
|
| 181 |
+
logger.error(f"Error creating destination: {str(e)}")
|
| 182 |
+
raise HTTPException(
|
| 183 |
+
status_code=500, detail=f"Error creating destination: {str(e)}"
|
| 184 |
+
)
|
| 185 |
+
|
| 186 |
+
|
| 187 |
+
@router.put("/{destination_id}")
|
| 188 |
+
async def update_destination(
|
| 189 |
+
destination_id: str, destination_data: dict, current_user: user_dependency
|
| 190 |
+
):
|
| 191 |
+
if current_user["role"] != "admin":
|
| 192 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 193 |
+
try:
|
| 194 |
+
# Add updated_at timestamp
|
| 195 |
+
destination_data["updated_at"] = datetime.utcnow()
|
| 196 |
+
|
| 197 |
+
# Update destination
|
| 198 |
+
result = await DestinationCRUD.update(
|
| 199 |
+
{"_id": ObjectId(destination_id)}, destination_data
|
| 200 |
+
)
|
| 201 |
+
|
| 202 |
+
if not result:
|
| 203 |
+
raise HTTPException(status_code=404, detail="Destination not found")
|
| 204 |
+
|
| 205 |
+
return JSONResponse(
|
| 206 |
+
content={"message": "Destination updated successfully"}, status_code=200
|
| 207 |
+
)
|
| 208 |
+
except Exception as e:
|
| 209 |
+
logger.error(f"Error updating destination: {str(e)}")
|
| 210 |
+
raise HTTPException(
|
| 211 |
+
status_code=500, detail=f"Error updating destination: {str(e)}"
|
| 212 |
+
)
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
@router.delete("/{destination_id}")
|
| 216 |
+
async def delete_destination(destination_id: str, current_user: user_dependency):
|
| 217 |
+
if current_user["role"] != "admin":
|
| 218 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 219 |
+
try:
|
| 220 |
+
# Delete destination
|
| 221 |
+
result = await DestinationCRUD.delete_one({"_id": ObjectId(destination_id)})
|
| 222 |
+
|
| 223 |
+
if not result:
|
| 224 |
+
raise HTTPException(status_code=404, detail="Destination not found")
|
| 225 |
+
|
| 226 |
+
return JSONResponse(
|
| 227 |
+
content={"message": "Destination deleted successfully"}, status_code=200
|
| 228 |
+
)
|
| 229 |
+
except Exception as e:
|
| 230 |
+
logger.error(f"Error deleting destination: {str(e)}")
|
| 231 |
+
raise HTTPException(
|
| 232 |
+
status_code=500, detail=f"Error deleting destination: {str(e)}"
|
| 233 |
+
)
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
@router.get("/")
|
| 237 |
+
async def get_all_destinations(current_user: user_dependency):
|
| 238 |
+
print("current_user", current_user)
|
| 239 |
+
if current_user["role"] != "admin":
|
| 240 |
+
raise HTTPException(status_code=403, detail="Unauthorized")
|
| 241 |
+
try:
|
| 242 |
+
# Get all destinations
|
| 243 |
+
destinations = await DestinationCRUD.find_all()
|
| 244 |
+
|
| 245 |
+
# Process results
|
| 246 |
+
serialized_data = []
|
| 247 |
+
for dest in destinations:
|
| 248 |
+
dest.pop("created_at")
|
| 249 |
+
dest.pop("updated_at")
|
| 250 |
+
dest.pop("expire_at")
|
| 251 |
+
dest["id"] = str(dest["_id"])
|
| 252 |
+
dest.pop("_id")
|
| 253 |
+
serialized_data.append(dest)
|
| 254 |
+
|
| 255 |
+
return JSONResponse(content={"data": serialized_data}, status_code=200)
|
| 256 |
+
except Exception as e:
|
| 257 |
+
logger.error(f"Error fetching destinations: {str(e)}")
|
| 258 |
+
raise HTTPException(
|
| 259 |
+
status_code=500, detail=f"Error fetching destinations: {str(e)}"
|
| 260 |
+
)
|
src/langgraph/multi_agent/chat/__pycache__/chat_flow.cpython-311.pyc
CHANGED
|
Binary files a/src/langgraph/multi_agent/chat/__pycache__/chat_flow.cpython-311.pyc and b/src/langgraph/multi_agent/chat/__pycache__/chat_flow.cpython-311.pyc differ
|
|
|
src/langgraph/tools/scheduling_tools.py
CHANGED
|
@@ -31,7 +31,13 @@ async def create_a_activity(
|
|
| 31 |
configuration = config.get("configurable", {})
|
| 32 |
user_id = configuration.get("user_id", None)
|
| 33 |
response = await create_a_activity_controller(
|
| 34 |
-
None,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 35 |
)
|
| 36 |
return response["message"]
|
| 37 |
except Exception as e:
|
|
|
|
| 31 |
configuration = config.get("configurable", {})
|
| 32 |
user_id = configuration.get("user_id", None)
|
| 33 |
response = await create_a_activity_controller(
|
| 34 |
+
None,
|
| 35 |
+
activity_category,
|
| 36 |
+
description,
|
| 37 |
+
start_time,
|
| 38 |
+
end_time,
|
| 39 |
+
user_id,
|
| 40 |
+
overlap_allow=False,
|
| 41 |
)
|
| 42 |
return response["message"]
|
| 43 |
except Exception as e:
|