"""Seed venues, events, media, and ticket types for Holi, Garba, Dandiya.""" import sys from datetime import datetime, timezone from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from sqlalchemy import select from app.db.session import SessionLocal from app.models.catalog import Event, EventMedia, TicketType, Venue from app.models.enums import EventStatus, EventType, TicketTypeStatus IMG = lambda photo_id, w=1600: f"https://images.unsplash.com/{photo_id}?auto=format&fit=crop&w={w}&q=80" GARBA_IMAGE = IMG("photo-1516450360457-62c5678aefa8") GARBA_IMAGE_ALT = IMG("photo-1578662996442-48f60103fc96") HOLI_IMAGE = IMG("photo-1524492412937-b28074a5d7da") DANDIYA_IMAGE = IMG("photo-1533174072545-7a4b6ad7a6c3") VENUES = [ { "slug": "palace-grounds", "name": "Palace Grounds", "area": "Vasanth Nagar", "address": "Palace Grounds, Jayamahal, Bengaluru, Karnataka 560006", "map_url": "https://maps.google.com/?q=Palace+Grounds+Bengaluru", "description": "Large open-air lawns suited to daylight Holi editions.", }, { "slug": "ktpo-whitefield", "name": "KTPO Convention Centre", "area": "Whitefield", "address": "KTPO, Whitefield Main Rd, Bengaluru, Karnataka 560066", "map_url": "https://maps.google.com/?q=KTPO+Whitefield", "description": "Convention-scale halls and floors for Garba and Dandiya nights.", }, { "slug": "hsr-layout-grounds", "name": "HSR Layout Club Grounds", "area": "HSR Layout", "address": "27th Main Rd, HSR Layout, Bengaluru, Karnataka 560102", "map_url": "https://maps.google.com/?q=HSR+Layout+Bengaluru", "description": "Neighbourhood grounds for intimate cultural socials.", }, ] EVENTS = [ { "slug": "rang-barse-palace-grounds-2026", "title": "Rang Barse — Palace Grounds", "category": EventType.holi, "venue_slug": "palace-grounds", "starts_at": datetime(2026, 3, 9, 10, 0, tzinfo=timezone.utc), "ends_at": datetime(2026, 3, 9, 18, 0, tzinfo=timezone.utc), "is_featured": True, "cover": HOLI_IMAGE, "cover_alt": "Crowd celebrating Holi with colour in the air", "description": "Daylight Holi with live dhol, curated gulal zones, and family-friendly lawns.", "media": [(HOLI_IMAGE, "Holi colour cloud above dancers", 0)], "tickets": [ ("General admission", "Full-day access with colour kit", 149900, 5000), ("Shade deck", "Reserved seating and meal credit", 299900, 400), ], }, { "slug": "navratri-nights-ktpo", "title": "Navratri Nights", "category": EventType.garba, "venue_slug": "ktpo-whitefield", "starts_at": datetime(2026, 10, 3, 19, 0, tzinfo=timezone.utc), "ends_at": datetime(2026, 10, 4, 1, 0, tzinfo=timezone.utc), "is_featured": True, "cover": GARBA_IMAGE, "cover_alt": "Women in traditional attire performing garba under evening lights", "description": "Whitefield Garba with live folk vocals, circular floor, and midnight raas.", "media": [ (GARBA_IMAGE, "Garba dancers in traditional dress", 0), (GARBA_IMAGE_ALT, "Garba dancers in coordinated circle", 1), ], "tickets": [ ("Dance floor", "Standing access to main circle", 99900, 3000), ("Balcony lounge", "Elevated seating", 189900, 250), ], }, { "slug": "hsr-dandiya-social-2026", "title": "HSR Dandiya Social", "category": EventType.dandiya, "venue_slug": "hsr-layout-grounds", "starts_at": datetime(2026, 10, 11, 20, 0, tzinfo=timezone.utc), "ends_at": datetime(2026, 10, 12, 1, 0, tzinfo=timezone.utc), "is_featured": False, "cover": DANDIYA_IMAGE, "cover_alt": "Evening lanterns at a cultural celebration", "description": "South Bengaluru Dandiya social with resident callers and midnight chai.", "media": [(DANDIYA_IMAGE, "Festival lights over the dance floor", 0)], "tickets": [("Early bird", "Full night access", 79900, 800)], }, ] def upsert_venue(db, data: dict) -> Venue: venue = db.scalar(select(Venue).where(Venue.slug == data["slug"])) if venue: for key, value in data.items(): setattr(venue, key, value) return venue venue = Venue(**data) db.add(venue) db.flush() return venue def seed() -> None: db = SessionLocal() try: venues_by_slug = {} for row in VENUES: venues_by_slug[row["slug"]] = upsert_venue(db, row) for row in EVENTS: venue = venues_by_slug[row["venue_slug"]] event = db.scalar(select(Event).where(Event.slug == row["slug"])) if not event: event = Event( slug=row["slug"], title=row["title"], category=row["category"], status=EventStatus.published, venue_id=venue.id, description=row["description"], starts_at=row["starts_at"], ends_at=row["ends_at"], is_featured=row["is_featured"], cover_image_url=row["cover"], cover_image_alt=row["cover_alt"], meta_description=row["description"][:300], ) db.add(event) db.flush() else: event.title = row["title"] event.category = row["category"] event.status = EventStatus.published event.venue_id = venue.id event.description = row["description"] event.starts_at = row["starts_at"] event.ends_at = row["ends_at"] event.is_featured = row["is_featured"] event.cover_image_url = row["cover"] event.cover_image_alt = row["cover_alt"] if not event.media: for url, alt, order in row["media"]: db.add( EventMedia( event_id=event.id, image_url=url, alt_text=alt, sort_order=order, ) ) if not event.ticket_types: for idx, (name, desc, price_paise, qty) in enumerate(row["tickets"]): db.add( TicketType( event_id=event.id, name=name, description=desc, price_paise=price_paise, quantity_total=qty, status=TicketTypeStatus.active, sort_order=idx, ) ) db.commit() print("Seeded catalog: venues, Holi, Garba, Dandiya events.") finally: db.close() if __name__ == "__main__": seed()