""" MySQL Database Configuration for Epic Travel & Expeditions Uses SQLAlchemy for MySQL connection """ from sqlalchemy import create_engine, Column, String, Text, Numeric, DateTime, JSON, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship from datetime import datetime import os from dotenv import load_dotenv from pathlib import Path # Load environment variables ROOT_DIR = Path(__file__).parent load_dotenv(ROOT_DIR / '.env') # MySQL Database URL MYSQL_USER = os.environ.get('MYSQL_USER') MYSQL_PASSWORD = os.environ.get('MYSQL_PASSWORD') MYSQL_HOST = os.environ.get('MYSQL_HOST', 'localhost') MYSQL_PORT = os.environ.get('MYSQL_PORT', '3306') MYSQL_DATABASE = os.environ.get('MYSQL_DATABASE') DATABASE_URL = f"mysql+pymysql://{MYSQL_USER}:{MYSQL_PASSWORD}@{MYSQL_HOST}:{MYSQL_PORT}/{MYSQL_DATABASE}?charset=utf8mb4" # Create engine engine = create_engine(DATABASE_URL, pool_pre_ping=True, pool_recycle=3600) # Create session SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine) # Base class for models Base = declarative_base() # Database Models class Destination(Base): __tablename__ = "destinations" id = Column(String(36), primary_key=True) name = Column(String(255), nullable=False, index=True) location = Column(String(255), nullable=False, index=True) description = Column(Text, nullable=False) image = Column(String(500), nullable=False) category = Column(String(50), nullable=False, index=True) rating = Column(Numeric(2, 1), nullable=False, default=4.5) price = Column(Numeric(10, 2), nullable=False) currency = Column(String(3), nullable=False, default='USD') created_at = Column(DateTime, nullable=False, default=datetime.utcnow) # Relationship specials = relationship("Special", back_populates="destination", cascade="all, delete-orphan") class Special(Base): __tablename__ = "specials" id = Column(String(36), primary_key=True) destination_id = Column(String(36), ForeignKey('destinations.id', ondelete='CASCADE'), nullable=False, index=True) discount = Column(Numeric(5, 2), nullable=False) end_date = Column(String(10), nullable=False) # Store as string YYYY-MM-DD highlights = Column(JSON, nullable=False) created_at = Column(DateTime, nullable=False, default=datetime.utcnow) # Relationship destination = relationship("Destination", back_populates="specials") class AdminUser(Base): __tablename__ = "admin_users" id = Column(String(36), primary_key=True) email = Column(String(255), nullable=False, unique=True, index=True) password_hash = Column(String(255), nullable=False) created_at = Column(DateTime, nullable=False, default=datetime.utcnow) class Contact(Base): __tablename__ = "contacts" id = Column(String(36), primary_key=True) name = Column(String(255), nullable=False) email = Column(String(255), nullable=False) message = Column(Text, nullable=False) created_at = Column(DateTime, nullable=False, default=datetime.utcnow, index=True) class NewsletterSubscriber(Base): __tablename__ = "newsletter_subscribers" id = Column(String(36), primary_key=True) email = Column(String(255), nullable=False, unique=True, index=True) subscribed_at = Column(DateTime, nullable=False, default=datetime.utcnow) # Dependency to get database session def get_db(): db = SessionLocal() try: yield db finally: db.close() # Create all tables (if they don't exist) def create_tables(): Base.metadata.create_all(bind=engine) if __name__ == "__main__": print("Creating database tables...") create_tables() print("Database tables created successfully!")