Skip to main content
Glama
booking_sessions.py10.8 kB
""" Hybrid Booking Sessions - Database Operations CRUD operations for hybrid booking sessions stored in PostgreSQL """ from typing import Optional, Dict, Any, List from datetime import datetime from sqlalchemy.orm import Session import logging from .models import HybridBookingSession from .database import get_db_session logger = logging.getLogger(__name__) class BookingSessionManager: """Manager for hybrid booking sessions in database""" @staticmethod def create_session( session_id: str, organizer_email: str, organizer_name: str, external_email: str, external_name: str, proposed_slots: List[Dict[str, str]], meeting_subject: str, meeting_duration: int, booking_url: str, internal_attendees: Optional[List[Dict[str, str]]] = None, attachments: Optional[List[Dict[str, Any]]] = None ) -> HybridBookingSession: """ Create a new hybrid booking session Args: session_id: Unique session identifier organizer_email: Email of meeting organizer organizer_name: Name of meeting organizer external_email: Email of external attendee external_name: Name of external attendee proposed_slots: List of proposed time slots meeting_subject: Meeting subject/title meeting_duration: Duration in minutes booking_url: URL for booking page internal_attendees: Optional list of internal attendees attachments: Optional list of file attachments (name, contentType, size, contentBytes) Returns: Created HybridBookingSession object """ try: with get_db_session() as db: booking_session = HybridBookingSession( session_id=session_id, organizer_email=organizer_email, organizer_name=organizer_name, external_email=external_email, external_name=external_name, proposed_slots=proposed_slots, meeting_subject=meeting_subject, meeting_duration=meeting_duration, booking_url=booking_url, internal_attendees=internal_attendees or [], attachments=attachments or [], status="pending" ) db.add(booking_session) db.commit() db.refresh(booking_session) logger.info(f"Created booking session: {session_id}") return booking_session except Exception as e: logger.error(f"Failed to create booking session {session_id}: {e}") raise @staticmethod def get_session(session_id: str) -> Optional[HybridBookingSession]: """ Get booking session by ID Args: session_id: Session identifier Returns: HybridBookingSession object or None if not found """ try: with get_db_session() as db: session = db.query(HybridBookingSession).filter( HybridBookingSession.session_id == session_id ).first() if session: # Detach from session to use outside context db.expunge(session) return session except Exception as e: logger.error(f"Failed to get booking session {session_id}: {e}") raise @staticmethod def update_session_status( session_id: str, status: str, confirmed_slot: Optional[Dict[str, str]] = None, event_id: Optional[str] = None ) -> bool: """ Update booking session status and confirmation details Args: session_id: Session identifier status: New status (pending, confirmed, expired, cancelled) confirmed_slot: Confirmed time slot (if applicable) event_id: Microsoft Graph event ID (if created) Returns: True if updated successfully, False otherwise """ try: with get_db_session() as db: session = db.query(HybridBookingSession).filter( HybridBookingSession.session_id == session_id ).first() if not session: logger.warning(f"Session {session_id} not found for update") return False session.status = status session.updated_at = datetime.utcnow() if confirmed_slot: session.confirmed_slot = confirmed_slot session.confirmed_at = datetime.utcnow() if event_id: session.event_id = event_id db.commit() logger.info(f"Updated booking session {session_id} to status: {status}") return True except Exception as e: logger.error(f"Failed to update booking session {session_id}: {e}") raise @staticmethod def update_proposed_slots( session_id: str, new_slots: List[Dict[str, str]] ) -> bool: """ Update proposed slots for a booking session Used when original slots are no longer available Args: session_id: Session identifier new_slots: New list of proposed time slots Returns: True if updated successfully, False otherwise """ try: with get_db_session() as db: session = db.query(HybridBookingSession).filter( HybridBookingSession.session_id == session_id ).first() if not session: logger.warning(f"Session {session_id} not found for slots update") return False session.proposed_slots = new_slots session.updated_at = datetime.utcnow() db.commit() logger.info(f"Updated proposed slots for session {session_id}: {len(new_slots)} new slots") return True except Exception as e: logger.error(f"Failed to update proposed slots for session {session_id}: {e}") raise @staticmethod def delete_session(session_id: str) -> bool: """ Delete a booking session Args: session_id: Session identifier Returns: True if deleted successfully, False otherwise """ try: with get_db_session() as db: session = db.query(HybridBookingSession).filter( HybridBookingSession.session_id == session_id ).first() if not session: logger.warning(f"Session {session_id} not found for deletion") return False db.delete(session) db.commit() logger.info(f"Deleted booking session: {session_id}") return True except Exception as e: logger.error(f"Failed to delete booking session {session_id}: {e}") raise @staticmethod def get_sessions_by_organizer(organizer_email: str) -> List[HybridBookingSession]: """ Get all booking sessions for an organizer Args: organizer_email: Organizer's email address Returns: List of HybridBookingSession objects """ try: with get_db_session() as db: sessions = db.query(HybridBookingSession).filter( HybridBookingSession.organizer_email == organizer_email ).order_by(HybridBookingSession.created_at.desc()).all() # Detach from session for session in sessions: db.expunge(session) return sessions except Exception as e: logger.error(f"Failed to get sessions for organizer {organizer_email}: {e}") raise @staticmethod def get_pending_sessions() -> List[HybridBookingSession]: """ Get all pending booking sessions Returns: List of pending HybridBookingSession objects """ try: with get_db_session() as db: sessions = db.query(HybridBookingSession).filter( HybridBookingSession.status == "pending" ).order_by(HybridBookingSession.created_at.desc()).all() # Detach from session for session in sessions: db.expunge(session) return sessions except Exception as e: logger.error(f"Failed to get pending sessions: {e}") raise @staticmethod def session_to_dict(session: HybridBookingSession) -> Dict[str, Any]: """ Convert HybridBookingSession object to dictionary Args: session: HybridBookingSession object Returns: Dictionary representation of session """ return { 'session_id': session.session_id, 'booking_url': session.booking_url, 'organizer_email': session.organizer_email, 'organizer_name': session.organizer_name, 'external_email': session.external_email, 'external_name': session.external_name, 'meeting_subject': session.meeting_subject, 'meeting_duration': session.meeting_duration, 'internal_attendees': session.internal_attendees, 'proposed_slots': session.proposed_slots, 'status': session.status, 'confirmed_slot': session.confirmed_slot, 'event_id': session.event_id, 'created_at': session.created_at.isoformat() if session.created_at else None, 'updated_at': session.updated_at.isoformat() if session.updated_at else None, 'confirmed_at': session.confirmed_at.isoformat() if session.confirmed_at else None }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/ilvolodel/iris-legacy'

If you have feedback or need assistance with the MCP directory API, please join our Discord server