Compare commits

..

9 Commits
1.2.9 ... 1.3.3

View File

@@ -4,401 +4,219 @@ from datetime import datetime
from ..dependencies import users_token, permissions_checker, database from ..dependencies import users_token, permissions_checker, database
from ..models import events, users from ..models import events, users
from pydantic import EmailStr from pydantic import EmailStr
from typing import Annotated from typing import Annotated, Union
from bson import ObjectId from bson import ObjectId
from datetime import datetime from datetime import datetime
router = APIRouter() router = APIRouter()
def build_location_filter(min_lat, max_lat, min_lon, max_lon):
"""Build location-based query filters."""
if min_lat is not None and max_lat is not None and min_lon is not None and max_lon is not None:
return [
{"latitude": {"$gte": min_lat}},
{"latitude": {"$lte": max_lat}},
{"longitude": {"$gte": min_lon}},
{"longitude": {"$lte": max_lon}},
]
return []
def build_datetime_filter(current_datetime):
"""Build filters for current datetime."""
if current_datetime:
return {
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{
"$and": [
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # Ongoing
{"end_date": None}, # No end date
]},
],
},
],
}
return None
def build_date_filter(start_date, end_date):
"""Build date range filters."""
if start_date and end_date:
return [
{"start_date": {"$gte": datetime.combine(start_date, datetime.min.time())}},
{"start_date": {"$lte": datetime.combine(end_date, datetime.max.time())}},
]
return []
def build_text_filter(item):
"""Build text-based search filters."""
if item:
return {
"$or": [
{"name": {"$regex": item, "$options": "i"}},
{"tags": {"$regex": item, "$options": "i"}},
{"organizers": {"$regex": item, "$options": "i"}},
]
}
return None
@router.get("/events", tags=["events"], response_model=list[events.EventOut]) @router.get("/events", tags=["events"], response_model=list[events.EventOut])
async def read_events(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], skip: int = 0, limit: int = 20, id_event: str | None = None, name: str | None = None, status: int = 1, tags: str | None = None, organizers: str | None = None, current_datetime: datetime | None = None, date_event: datetime |None = None): async def read_events(
authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))],
skip: int = 0,
limit: int = 20,
id_event: str | None = None,
name: str | None = None,
status: int = 1,
tags: str | None = None,
organizers: str | None = None,
current_datetime: datetime | None = None,
date_event: datetime | None = None,
start_date: datetime | None = None,
end_date: datetime | None = None,
):
# Validate `skip` and `limit`
if limit < 1 or skip < 0 or limit < skip: if limit < 1 or skip < 0 or limit < skip:
raise HTTPException( raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, status_code=status.HTTP_400_BAD_REQUEST,
detail="skip should be greater than 0 and limit should be greater than 1. Limit should be greater than skip" detail="`skip` should be >= 0 and `limit` should be > 0 and greater than `skip`.",
) )
limit = limit + skip limit = limit + skip
listEvents = []
# Initialize filters
filters = []
# Add status filter
filters.append({"status": {"$eq": status}})
# Add date filters
if date_event:
start_of_day = datetime.combine(date_event, datetime.min.time())
end_of_day = datetime.combine(date_event, datetime.max.time())
filters.extend(build_date_filter(start_of_day, end_of_day))
elif start_date and end_date:
filters.extend(build_date_filter(start_date, end_date))
# Add current datetime filter
datetime_filter = build_datetime_filter(current_datetime)
if datetime_filter:
filters.append(datetime_filter)
# Add text-based filters
if name:
filters.append(build_text_filter(name))
if tags:
filters.append({"tags": {"$eq": tags}})
if organizers:
filters.append({"organizers": {"$eq": organizers}})
# Add ID filter
if id_event:
try:
event_id = ObjectId(id_event)
filters.append({"_id": {"$eq": event_id}})
except Exception:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid event ID format.")
# Combine all filters
object_search = {"$and": filters} if filters else {}
# Fetch and return results
event_repository = events.EventRepository(database=database.database) event_repository = events.EventRepository(database=database.database)
object_search = {} list_events = []
if date_event is not None: for event_index in event_repository.find_by(object_search, limit=limit, skip=skip):
start_of_day = datetime.combine(date_event, datetime.min.time()) # 2024-11-23 00:00:00 event = events.EventOut(
end_of_day = datetime.combine(date_event, datetime.max.time()) id=event_index.id,
if current_datetime is not None: tags=event_index.tags,
object_search ={ imgUrl=event_index.imgUrl,
"$or": [{"start_date": {"$gte": current_datetime}}, # Upcoming events name=event_index.name,
{"$and": [ # Ongoing events description=event_index.description,
{"start_date": {"$lte": current_datetime}}, # Already started place=event_index.place,
{"$or": [ status=event_index.status,
{"end_date": {"$gte": current_datetime}}, # End date in the future start_date=event_index.start_date,
{"end_date": None} # No end date set end_date=event_index.end_date,
]} )
]} list_events.append(event)
]
} return list_events
if date_event is not None:
object_search ={
"$and": [{"start_date": {"$gte": start_of_day}}, @router.get("/events/search", tags=["events"], response_model=List[events.EventOut])
{"start_date": {"$lte": end_of_day}} # Upcoming events async def search_events(
] authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))],
} skip: int = 0,
if status is not 1: limit: int = 20,
object_search = {"status":{"$eq": status}} item: Union[str, None] = None,
if current_datetime is not None: status: int = 1,
object_search = { "$and": [ {"status":{"$eq": status}}, min_lat: Union[float, None] = None,
{ max_lat: Union[float, None] = None,
"$or": [ min_lon: Union[float, None] = None,
{"start_date": {"$gte": current_datetime}}, # Upcoming events max_lon: Union[float, None] = None,
{"$and": [ # Ongoing events current_datetime: Union[datetime, None] = None,
{"start_date": {"$lte": current_datetime}}, # Already started date_event: Union[datetime, None] = None,
{"$or": [ start_date: Union[datetime, None] = None,
{"end_date": {"$gte": current_datetime}}, # End date in the future end_date: Union[datetime, None] = None,
{"end_date": None} # No end date set tags: Union[List[str], None] = None,
]} ):
]} if limit < 1 or skip < 0 or limit < skip:
] raise HTTPException(
} status_code=status.HTTP_400_BAD_REQUEST,
]} detail="`skip` should be >= 0 and `limit` should be > 0 and greater than `skip`.",
if date_event is not None: )
object_search = { "$and": [ {"status":{"$eq": status}}, limit = limit + skip
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}} # Initialize filters
]} filters = [{"status": {"$eq": status}}]
# Date filters
if date_event:
start_of_day = datetime.combine(date_event, datetime.min.time())
end_of_day = datetime.combine(date_event, datetime.max.time())
filters.extend(build_date_filter(start_of_day, end_of_day))
else:
filters.extend(build_date_filter(start_date, end_date))
# Add location filter
filters.extend(build_location_filter(min_lat, max_lat, min_lon, max_lon))
# Add datetime filter
datetime_filter = build_datetime_filter(current_datetime)
if datetime_filter:
filters.append(datetime_filter)
# Add text filter
text_filter = build_text_filter(item)
if text_filter:
filters.append(text_filter)
if tags is not None: if tags is not None:
object_search = {"$and":[{"tags":{"$eq": tags}}, {"status":{"$eq":status}}]} filters.append({"tags": {"$in": tags}})
if current_datetime is not None:
object_search = {"$and":[{"tags":{"$eq": tags}},
{"status":{"$eq":status}},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]
}
if date_event is not None:
object_search = {"$and":[{"tags":{"$eq": tags}},
{"status":{"$eq":status}},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]
}
if organizers is not None:
object_search = {"$and":[{"organizers":{"$eq": organizers}}, {"status":{"$eq":status}}]}
if current_datetime is not None:
object_search = {"$and":[{"organizers":{"$eq": organizers}},
{"status":{"$eq":status}},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]}
if date_event is not None:
object_search = {"$and":[{"organizers":{"$eq": organizers}},
{"status":{"$eq":status}},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]}
if id_event is not None:
eventid = ObjectId(id_event)
object_search = {"$and":[{"id":{"$regex": eventid}}, {"status":{"$eq":status}}]}
if current_datetime is not None:
object_search = {"$and":[{"id":{"$regex": eventid}},
{"status":{"$eq":status}},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]}
if date_event is not None:
object_search = {"$and":[{"id":{"$regex": eventid}},
{"status":{"$eq":status}},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]}
if name is not None:
object_search = {"$and":[{"name":{"$regex": name}}, {"status":{"$eq":status}}]}
if current_datetime is not None:
object_search = {"$and":[{"name":{"$regex": name}},
{"status":{"$eq":status}},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]}
if date_event is not None:
object_search = {"$and":[{"name":{"$regex": name}},
{"status":{"$eq":status}},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]}
for event_index in event_repository.find_by(object_search, limit=limit, skip=skip): # Combine filters
event = events.EventOut(id=event_index.id, tags=event_index.tags, imgUrl=event_index.imgUrl, name=event_index.name, description=event_index.description, place=event_index.place, status=event_index.status, start_date=event_index.start_date, end_date=event_index.end_date) object_search = {"$and": filters} if filters else {}
listEvents.append(event)
return listEvents
# Fetch and return results
@router.get("/events/search", tags=["events"], response_model=list[events.EventOut])
async def search_events(authorize: Annotated[bool, Depends(permissions_checker.PermissionChecker(roles=["Admin", "User"]))], skip: int = 0, limit: int = 20, item: str | None = None, status: int = 1, min_lat: float | None = None, max_lat: float | None = None, min_lon: float | None = None, max_lon: float | None = None, current_datetime: datetime | None = None, date_event: datetime | None = None):
if limit < 1 or skip < 0 or limit < skip:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="skip should be greater than 0 and limit should be greater than 1. Limit should be greater than skip"
)
limit = limit + skip
listEvents = []
event_repository = events.EventRepository(database=database.database) event_repository = events.EventRepository(database=database.database)
object_search = {} list_events = []
if date_event is not None:
start_of_day = datetime.combine(date_event, datetime.min.time()) # 2024-11-23 00:00:00
end_of_day = datetime.combine(date_event, datetime.max.time())
if min_lat is not None and max_lat is not None and min_lon is not None and max_lon is not None:
object_search = {
"$and": [
{"status": {"$eq": status}},
{
"latitude": {"$gte": min_lat}, # Minimum latitude
},
{
"latitude": {"$lte": max_lat}, # Maximum latitude
},
{
"longitude": {"$gte": min_lon}, # Minimum longitude
},
{
"longitude": {"$lte": max_lon}, # Maximum longitude
}
]
}
if current_datetime is not None:
object_search = {
"$and": [
{"status": {"$eq": status}},
{
"latitude": {"$gte": min_lat}, # Minimum latitude
},
{
"latitude": {"$lte": max_lat}, # Maximum latitude
},
{
"longitude": {"$gte": min_lon}, # Minimum longitude
},
{
"longitude": {"$lte": max_lon}, # Maximum longitude
},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]
}
if date_event is not None:
object_search = {
"$and": [
{"status": {"$eq": status}},
{
"latitude": {"$gte": min_lat}, # Minimum latitude
},
{
"latitude": {"$lte": max_lat}, # Maximum latitude
},
{
"longitude": {"$gte": min_lon}, # Minimum longitude
},
{
"longitude": {"$lte": max_lon}, # Maximum longitude
},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]
}
if item is not None:
object_search = {
"$and": [
{
"$or": [
{"name": {"$regex": item}},
{"tags": {"$regex": item}},
{"organizers": {"$regex": item}}
]
},
{"status": {"$eq": status}}
]
}
if current_datetime is not None:
object_search = {
"$and": [
{
"$or": [
{"name": {"$regex": item}},
{"tags": {"$regex": item}},
{"organizers": {"$regex": item}}
]
},
{"status": {"$eq": status}},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]
}
if date_event is not None:
object_search = {
"$and": [
{
"$or": [
{"name": {"$regex": item}},
{"tags": {"$regex": item}},
{"organizers": {"$regex": item}}
]
},
{"status": {"$eq": status}},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]
}
if min_lat is not None and max_lat is not None and min_lon is not None and max_lon is not None:
object_search = {
"$and": [
{
"$or": [
{"name": {"$regex": item}},
{"tags": {"$regex": item}},
{"organizers": {"$regex": item}}
]
},
{"status": {"$eq": status}},
{
"latitude": {"$gte": min_lat}, # Minimum latitude
},
{
"latitude": {"$lte": max_lat}, # Maximum latitude
},
{
"longitude": {"$gte": min_lon}, # Minimum longitude
},
{
"longitude": {"$lte": max_lon}, # Maximum longitude
}
]
}
if current_datetime is not None:
object_search = {
"$and": [
{
"$or": [
{"name": {"$regex": item}},
{"tags": {"$regex": item}},
{"organizers": {"$regex": item}}
]
},
{"status": {"$eq": status}},
{
"latitude": {"$gte": min_lat}, # Minimum latitude
},
{
"latitude": {"$lte": max_lat}, # Maximum latitude
},
{
"longitude": {"$gte": min_lon}, # Minimum longitude
},
{
"longitude": {"$lte": max_lon}, # Maximum longitude
},
{
"$or": [
{"start_date": {"$gte": current_datetime}}, # Upcoming events
{"$and": [ # Ongoing events
{"start_date": {"$lte": current_datetime}}, # Already started
{"$or": [
{"end_date": {"$gte": current_datetime}}, # End date in the future
{"end_date": None} # No end date set
]}
]}
]
}
]
}
if date_event is not None:
object_search = {
"$and": [
{
"$or": [
{"name": {"$regex": item}},
{"tags": {"$regex": item}},
{"organizers": {"$regex": item}}
]
},
{"status": {"$eq": status}},
{
"latitude": {"$gte": min_lat}, # Minimum latitude
},
{
"latitude": {"$lte": max_lat}, # Maximum latitude
},
{
"longitude": {"$gte": min_lon}, # Minimum longitude
},
{
"longitude": {"$lte": max_lon}, # Maximum longitude
},
{"start_date": {"$gte": start_of_day}},
{"start_date": {"$lte": end_of_day}}
]
}
for event_index in event_repository.find_by(object_search, limit=limit, skip=skip): for event_index in event_repository.find_by(object_search, limit=limit, skip=skip):
event = events.EventOut(id=event_index.id, tags=event_index.tags, imgUrl=event_index.imgUrl, name=event_index.name, description=event_index.description, place=event_index.place, status=event_index.status, start_date=event_index.start_date, end_date=event_index.end_date) event = events.EventOut(
listEvents.append(event) id=event_index.id,
return listEvents tags=event_index.tags,
imgUrl=event_index.imgUrl,
name=event_index.name,
description=event_index.description,
place=event_index.place,
status=event_index.status,
start_date=event_index.start_date,
end_date=event_index.end_date,
)
list_events.append(event)
return list_events
@router.get("/events/me",tags=["events"]) @router.get("/events/me",tags=["events"])