Files
bakery-ia/services/tenant/app/repositories/event_repository.py
2025-11-05 13:34:56 +01:00

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