# services/external/app/models/calendar.py """ School Calendar and Tenant Location Context Models Hyperlocal data for demand forecasting """ from sqlalchemy import Column, String, DateTime, Index, Boolean from sqlalchemy.dialects.postgresql import UUID, JSONB from datetime import datetime import uuid from app.core.database import Base class SchoolCalendar(Base): """City-based school calendar data for forecasting""" __tablename__ = "school_calendars" id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) city_id = Column(String(50), nullable=False, index=True) calendar_name = Column(String(100), nullable=False) school_type = Column(String(20), nullable=False) # primary, secondary, university academic_year = Column(String(10), nullable=False) # e.g., "2024-2025" # Holiday periods as array of date ranges # Example: [ # {"name": "Christmas", "start": "2024-12-20", "end": "2025-01-08"}, # {"name": "Easter", "start": "2025-04-10", "end": "2025-04-21"}, # {"name": "Summer", "start": "2025-06-23", "end": "2025-09-09"} # ] holiday_periods = Column(JSONB, nullable=False, default=list) # School hours configuration # Example: { # "morning_start": "09:00", # "morning_end": "14:00", # "afternoon_start": "15:00", # if applicable # "afternoon_end": "17:00", # "has_afternoon_session": false # } school_hours = Column(JSONB, nullable=False, default=dict) # Metadata source = Column(String(100), nullable=True) # e.g., "madrid_education_dept" enabled = Column(Boolean, default=True, nullable=False) created_at = Column(DateTime(timezone=True), default=datetime.utcnow) updated_at = Column(DateTime(timezone=True), default=datetime.utcnow, onupdate=datetime.utcnow) __table_args__ = ( Index('idx_school_calendar_city_year', 'city_id', 'academic_year'), Index('idx_school_calendar_city_type', 'city_id', 'school_type'), ) class TenantLocationContext(Base): """Tenant-specific location context for hyperlocal forecasting""" __tablename__ = "tenant_location_contexts" tenant_id = Column(UUID(as_uuid=True), primary_key=True) city_id = Column(String(50), nullable=False, index=True) # School calendar assignment school_calendar_id = Column(UUID(as_uuid=True), nullable=True, index=True) # Hyperlocal context neighborhood = Column(String(100), nullable=True) # Custom local events specific to this tenant's location # Example: [ # {"name": "Neighborhood Festival", "date": "2025-06-15", "impact": "high"}, # {"name": "Local Market Day", "date": "2025-05-20", "impact": "medium"} # ] local_events = Column(JSONB, nullable=True, default=list) # Additional metadata notes = Column(String(500), nullable=True) created_at = Column(DateTime(timezone=True), default=datetime.utcnow) updated_at = Column(DateTime(timezone=True), default=datetime.utcnow, onupdate=datetime.utcnow) __table_args__ = ( Index('idx_tenant_location_calendar', 'school_calendar_id'), )