auto-commit for 8a62051e-b038-4363-a62d-7047e3d6e102

This commit is contained in:
emergent-agent-e1
2026-03-16 18:22:14 +00:00
parent 706e3e2eb6
commit 6a9e343332
16 changed files with 1510 additions and 212 deletions
+224 -52
View File
@@ -1,15 +1,15 @@
from fastapi import FastAPI, APIRouter
from fastapi import FastAPI
from dotenv import load_dotenv
from starlette.middleware.cors import CORSMiddleware
from motor.motor_asyncio import AsyncIOMotorClient
import os
import logging
from pathlib import Path
from pydantic import BaseModel, Field, ConfigDict
from typing import List
import uuid
from datetime import datetime, timezone
from auth import hash_password
from datetime import datetime
# Import route modules
from routes import auth_routes, destination_routes, special_routes, other_routes
ROOT_DIR = Path(__file__).parent
load_dotenv(ROOT_DIR / '.env')
@@ -19,60 +19,30 @@ mongo_url = os.environ['MONGO_URL']
client = AsyncIOMotorClient(mongo_url)
db = client[os.environ['DB_NAME']]
# Create the main app without a prefix
app = FastAPI()
# Inject database into route modules
auth_routes.set_db(db)
destination_routes.set_db(db)
special_routes.set_db(db)
other_routes.set_db(db)
# Create a router with the /api prefix
api_router = APIRouter(prefix="/api")
# Create the main app
app = FastAPI(title="Epic Travel & Destinations API")
# Include routers
app.include_router(auth_routes.router)
app.include_router(destination_routes.router)
app.include_router(special_routes.router)
app.include_router(other_routes.router)
# Define Models
class StatusCheck(BaseModel):
model_config = ConfigDict(extra="ignore") # Ignore MongoDB's _id field
id: str = Field(default_factory=lambda: str(uuid.uuid4()))
client_name: str
timestamp: datetime = Field(default_factory=lambda: datetime.now(timezone.utc))
class StatusCheckCreate(BaseModel):
client_name: str
# Add your routes to the router instead of directly to app
@api_router.get("/")
# Health check endpoint
@app.get("/api")
async def root():
return {"message": "Hello World"}
@api_router.post("/status", response_model=StatusCheck)
async def create_status_check(input: StatusCheckCreate):
status_dict = input.model_dump()
status_obj = StatusCheck(**status_dict)
# Convert to dict and serialize datetime to ISO string for MongoDB
doc = status_obj.model_dump()
doc['timestamp'] = doc['timestamp'].isoformat()
_ = await db.status_checks.insert_one(doc)
return status_obj
@api_router.get("/status", response_model=List[StatusCheck])
async def get_status_checks():
# Exclude MongoDB's _id field from the query results
status_checks = await db.status_checks.find({}, {"_id": 0}).to_list(1000)
# Convert ISO string timestamps back to datetime objects
for check in status_checks:
if isinstance(check['timestamp'], str):
check['timestamp'] = datetime.fromisoformat(check['timestamp'])
return status_checks
# Include the router in the main app
app.include_router(api_router)
return {"message": "Epic Travel API is running", "status": "healthy"}
app.add_middleware(
CORSMiddleware,
allow_credentials=True,
allow_origins=os.environ.get('CORS_ORIGINS', '*').split(','),
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
@@ -84,6 +54,208 @@ logging.basicConfig(
)
logger = logging.getLogger(__name__)
@app.on_event("startup")
async def startup_db_client():
"""Initialize database with seed data if empty"""
try:
# Check if admin user exists, if not create one
admin_exists = await db.admin_users.find_one({"email": "admin@epictravel.com"})
if not admin_exists:
admin_data = {
"id": "admin-1",
"email": "admin@epictravel.com",
"password_hash": hash_password("admin123"),
"created_at": datetime.utcnow()
}
await db.admin_users.insert_one(admin_data)
logger.info("Default admin user created")
# Check if destinations exist, if not seed initial data
dest_count = await db.destinations.count_documents({})
if dest_count == 0:
# Seed initial destinations
initial_destinations = [
{
"id": "1",
"name": "Paris",
"location": "France",
"description": "Experience the romance and elegance of the City of Light. Visit iconic landmarks like the Eiffel Tower, Louvre Museum, and stroll along the Champs-Élysées.",
"image": "https://images.unsplash.com/photo-1502602898657-3e91760cbb34?w=800&q=80",
"category": "City",
"rating": 4.9,
"price": 1299,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "2",
"name": "Bali",
"location": "Indonesia",
"description": "Discover tropical paradise with stunning beaches, ancient temples, lush rice terraces, and vibrant culture in this Indonesian gem.",
"image": "https://images.unsplash.com/photo-1537996194471-e657df975ab4?w=800&q=80",
"category": "Beach",
"rating": 4.8,
"price": 899,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "3",
"name": "Tokyo",
"location": "Japan",
"description": "Immerse yourself in the perfect blend of ancient tradition and cutting-edge technology in Japan's bustling capital city.",
"image": "https://images.unsplash.com/photo-1540959733332-eab4deabeeaf?w=800&q=80",
"category": "City",
"rating": 4.9,
"price": 1499,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "4",
"name": "Santorini",
"location": "Greece",
"description": "Marvel at breathtaking sunsets, whitewashed buildings, and crystal-clear waters in this stunning Greek island paradise.",
"image": "https://images.unsplash.com/photo-1613395877344-13d4a8e0d49e?w=800&q=80",
"category": "Beach",
"rating": 4.9,
"price": 1199,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "5",
"name": "Iceland",
"location": "Iceland",
"description": "Witness the Northern Lights, explore glaciers, geysers, and volcanic landscapes in this land of fire and ice.",
"image": "https://images.unsplash.com/photo-1504829857797-ddff29c27927?w=800&q=80",
"category": "Adventure",
"rating": 4.8,
"price": 1699,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "6",
"name": "Dubai",
"location": "UAE",
"description": "Experience luxury and innovation in the desert with world-class shopping, stunning architecture, and endless entertainment.",
"image": "https://images.unsplash.com/photo-1512453979798-5ea266f8880c?w=800&q=80",
"category": "City",
"rating": 4.7,
"price": 1399,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "7",
"name": "Maldives",
"location": "Maldives",
"description": "Relax in overwater bungalows, dive in pristine coral reefs, and enjoy the ultimate tropical island getaway.",
"image": "https://images.unsplash.com/photo-1514282401047-d79a71a590e8?w=800&q=80",
"category": "Beach",
"rating": 5.0,
"price": 2199,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "8",
"name": "New York",
"location": "USA",
"description": "Explore the city that never sleeps with iconic landmarks, world-class museums, Broadway shows, and diverse neighborhoods.",
"image": "https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?w=800&q=80",
"category": "City",
"rating": 4.8,
"price": 1099,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "9",
"name": "Machu Picchu",
"location": "Peru",
"description": "Trek to the ancient Incan citadel nestled high in the Andes Mountains, one of the New Seven Wonders of the World.",
"image": "https://images.unsplash.com/photo-1587595431973-160d0d94add1?w=800&q=80",
"category": "Adventure",
"rating": 4.9,
"price": 1299,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "10",
"name": "Swiss Alps",
"location": "Switzerland",
"description": "Ski pristine slopes, hike mountain trails, and enjoy charming alpine villages with breathtaking mountain vistas.",
"image": "https://images.unsplash.com/photo-1531366936337-7c912a4589a7?w=800&q=80",
"category": "Adventure",
"rating": 4.9,
"price": 1799,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "11",
"name": "Venice",
"location": "Italy",
"description": "Glide through romantic canals, admire Renaissance architecture, and savor authentic Italian cuisine in this unique floating city.",
"image": "https://images.unsplash.com/photo-1523906834658-6e24ef2386f9?w=800&q=80",
"category": "City",
"rating": 4.8,
"price": 1149,
"currency": "USD",
"created_at": datetime.utcnow()
},
{
"id": "12",
"name": "Safari Kenya",
"location": "Kenya",
"description": "Witness the Great Migration, spot the Big Five, and experience the raw beauty of African wilderness.",
"image": "https://images.unsplash.com/photo-1516426122078-c23e76319801?w=800&q=80",
"category": "Adventure",
"rating": 4.9,
"price": 2499,
"currency": "USD",
"created_at": datetime.utcnow()
}
]
await db.destinations.insert_many(initial_destinations)
logger.info(f"Seeded {len(initial_destinations)} initial destinations")
# Seed initial specials
initial_specials = [
{
"id": "special-1",
"destination_id": "2",
"discount": 25,
"end_date": "2025-02-28",
"highlights": ["Free spa treatment", "Complimentary airport transfer", "Sunset dinner cruise"],
"created_at": datetime.utcnow()
},
{
"id": "special-2",
"destination_id": "4",
"discount": 30,
"end_date": "2025-03-15",
"highlights": ["Wine tasting tour", "Private yacht excursion", "Luxury accommodation upgrade"],
"created_at": datetime.utcnow()
},
{
"id": "special-3",
"destination_id": "7",
"discount": 20,
"end_date": "2025-02-20",
"highlights": ["Snorkeling adventure", "Couples massage", "Romantic beach dinner"],
"created_at": datetime.utcnow()
}
]
await db.specials.insert_many(initial_specials)
logger.info(f"Seeded {len(initial_specials)} initial specials")
except Exception as e:
logger.error(f"Error during startup: {str(e)}")
@app.on_event("shutdown")
async def shutdown_db_client():
client.close()
client.close()