284 lines
8.4 KiB
Python
284 lines
8.4 KiB
Python
"""
|
|
Event Repository
|
|
Data access layer for events
|
|
"""
|
|
|
|
from typing import List, Optional, Dict, Any
|
|
from datetime import date, datetime
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from sqlalchemy import select, and_, or_, func
|
|
from uuid import UUID
|
|
import structlog
|
|
|
|
from app.models.events import Event, EventTemplate
|
|
from shared.database.repository import BaseRepository
|
|
|
|
logger = structlog.get_logger()
|
|
|
|
|
|
class EventRepository(BaseRepository[Event]):
|
|
"""Repository for event management"""
|
|
|
|
def __init__(self, session: AsyncSession):
|
|
super().__init__(Event, session)
|
|
|
|
async def get_events_by_date_range(
|
|
self,
|
|
tenant_id: UUID,
|
|
start_date: date,
|
|
end_date: date,
|
|
event_types: List[str] = None,
|
|
confirmed_only: bool = False
|
|
) -> List[Event]:
|
|
"""
|
|
Get events within a date range.
|
|
|
|
Args:
|
|
tenant_id: Tenant UUID
|
|
start_date: Start date (inclusive)
|
|
end_date: End date (inclusive)
|
|
event_types: Optional filter by event types
|
|
confirmed_only: Only return confirmed events
|
|
|
|
Returns:
|
|
List of Event objects
|
|
"""
|
|
try:
|
|
query = select(Event).where(
|
|
and_(
|
|
Event.tenant_id == tenant_id,
|
|
Event.event_date >= start_date,
|
|
Event.event_date <= end_date
|
|
)
|
|
)
|
|
|
|
if event_types:
|
|
query = query.where(Event.event_type.in_(event_types))
|
|
|
|
if confirmed_only:
|
|
query = query.where(Event.is_confirmed == True)
|
|
|
|
query = query.order_by(Event.event_date)
|
|
|
|
result = await self.session.execute(query)
|
|
events = result.scalars().all()
|
|
|
|
logger.debug("Retrieved events by date range",
|
|
tenant_id=str(tenant_id),
|
|
start_date=start_date.isoformat(),
|
|
end_date=end_date.isoformat(),
|
|
count=len(events))
|
|
|
|
return list(events)
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to get events by date range",
|
|
tenant_id=str(tenant_id),
|
|
error=str(e))
|
|
return []
|
|
|
|
async def get_events_for_date(
|
|
self,
|
|
tenant_id: UUID,
|
|
event_date: date
|
|
) -> List[Event]:
|
|
"""
|
|
Get all events for a specific date.
|
|
|
|
Args:
|
|
tenant_id: Tenant UUID
|
|
event_date: Date to get events for
|
|
|
|
Returns:
|
|
List of Event objects
|
|
"""
|
|
try:
|
|
query = select(Event).where(
|
|
and_(
|
|
Event.tenant_id == tenant_id,
|
|
Event.event_date == event_date
|
|
)
|
|
).order_by(Event.start_time)
|
|
|
|
result = await self.session.execute(query)
|
|
events = result.scalars().all()
|
|
|
|
return list(events)
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to get events for date",
|
|
tenant_id=str(tenant_id),
|
|
error=str(e))
|
|
return []
|
|
|
|
async def get_upcoming_events(
|
|
self,
|
|
tenant_id: UUID,
|
|
days_ahead: int = 30,
|
|
limit: int = 100
|
|
) -> List[Event]:
|
|
"""
|
|
Get upcoming events.
|
|
|
|
Args:
|
|
tenant_id: Tenant UUID
|
|
days_ahead: Number of days to look ahead
|
|
limit: Maximum number of events to return
|
|
|
|
Returns:
|
|
List of upcoming Event objects
|
|
"""
|
|
try:
|
|
from datetime import date, timedelta
|
|
|
|
today = date.today()
|
|
future_date = today + timedelta(days=days_ahead)
|
|
|
|
query = select(Event).where(
|
|
and_(
|
|
Event.tenant_id == tenant_id,
|
|
Event.event_date >= today,
|
|
Event.event_date <= future_date
|
|
)
|
|
).order_by(Event.event_date).limit(limit)
|
|
|
|
result = await self.session.execute(query)
|
|
events = result.scalars().all()
|
|
|
|
return list(events)
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to get upcoming events",
|
|
tenant_id=str(tenant_id),
|
|
error=str(e))
|
|
return []
|
|
|
|
async def create_event(self, event_data: Dict[str, Any]) -> Event:
|
|
"""Create a new event"""
|
|
try:
|
|
event = Event(**event_data)
|
|
self.session.add(event)
|
|
await self.session.flush()
|
|
|
|
logger.info("Created event",
|
|
event_id=str(event.id),
|
|
event_name=event.event_name,
|
|
event_date=event.event_date.isoformat())
|
|
|
|
return event
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to create event", error=str(e))
|
|
raise
|
|
|
|
async def update_event_actual_impact(
|
|
self,
|
|
event_id: UUID,
|
|
actual_impact_multiplier: float,
|
|
actual_sales_increase_percent: float
|
|
) -> Optional[Event]:
|
|
"""
|
|
Update event with actual impact after it occurs.
|
|
|
|
Args:
|
|
event_id: Event UUID
|
|
actual_impact_multiplier: Actual demand multiplier observed
|
|
actual_sales_increase_percent: Actual sales increase percentage
|
|
|
|
Returns:
|
|
Updated Event or None
|
|
"""
|
|
try:
|
|
event = await self.get(event_id)
|
|
if not event:
|
|
return None
|
|
|
|
event.actual_impact_multiplier = actual_impact_multiplier
|
|
event.actual_sales_increase_percent = actual_sales_increase_percent
|
|
|
|
await self.session.flush()
|
|
|
|
logger.info("Updated event actual impact",
|
|
event_id=str(event_id),
|
|
actual_multiplier=actual_impact_multiplier)
|
|
|
|
return event
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to update event actual impact",
|
|
event_id=str(event_id),
|
|
error=str(e))
|
|
return None
|
|
|
|
async def get_events_by_type(
|
|
self,
|
|
tenant_id: UUID,
|
|
event_type: str,
|
|
limit: int = 100
|
|
) -> List[Event]:
|
|
"""Get events by type"""
|
|
try:
|
|
query = select(Event).where(
|
|
and_(
|
|
Event.tenant_id == tenant_id,
|
|
Event.event_type == event_type
|
|
)
|
|
).order_by(Event.event_date.desc()).limit(limit)
|
|
|
|
result = await self.session.execute(query)
|
|
events = result.scalars().all()
|
|
|
|
return list(events)
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to get events by type",
|
|
tenant_id=str(tenant_id),
|
|
event_type=event_type,
|
|
error=str(e))
|
|
return []
|
|
|
|
|
|
class EventTemplateRepository(BaseRepository[EventTemplate]):
|
|
"""Repository for event template management"""
|
|
|
|
def __init__(self, session: AsyncSession):
|
|
super().__init__(EventTemplate, session)
|
|
|
|
async def get_active_templates(self, tenant_id: UUID) -> List[EventTemplate]:
|
|
"""Get all active event templates for a tenant"""
|
|
try:
|
|
query = select(EventTemplate).where(
|
|
and_(
|
|
EventTemplate.tenant_id == tenant_id,
|
|
EventTemplate.is_active == True
|
|
)
|
|
).order_by(EventTemplate.template_name)
|
|
|
|
result = await self.session.execute(query)
|
|
templates = result.scalars().all()
|
|
|
|
return list(templates)
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to get active templates",
|
|
tenant_id=str(tenant_id),
|
|
error=str(e))
|
|
return []
|
|
|
|
async def create_template(self, template_data: Dict[str, Any]) -> EventTemplate:
|
|
"""Create a new event template"""
|
|
try:
|
|
template = EventTemplate(**template_data)
|
|
self.session.add(template)
|
|
await self.session.flush()
|
|
|
|
logger.info("Created event template",
|
|
template_id=str(template.id),
|
|
template_name=template.template_name)
|
|
|
|
return template
|
|
|
|
except Exception as e:
|
|
logger.error("Failed to create event template", error=str(e))
|
|
raise
|