112 lines
3.5 KiB
Python
112 lines
3.5 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlmodel import Session, select, func
|
|
from typing import List, Optional
|
|
from database import get_session
|
|
from models import (
|
|
Vertical, Artist, Musician, BandMembership,
|
|
PerformanceGuest, Performance, Show, Song, Venue
|
|
)
|
|
|
|
router = APIRouter(prefix="/bands", tags=["bands"])
|
|
|
|
|
|
@router.get("")
|
|
async def list_bands(
|
|
scene: Optional[str] = None,
|
|
is_featured: Optional[bool] = None,
|
|
session: Session = Depends(get_session)
|
|
):
|
|
"""List all active bands, optionally filtered"""
|
|
query = select(Vertical).where(Vertical.is_active == True)
|
|
|
|
if is_featured is not None:
|
|
query = query.where(Vertical.is_featured == is_featured)
|
|
|
|
bands = session.exec(query.order_by(Vertical.name)).all()
|
|
return bands
|
|
|
|
|
|
@router.get("/{slug}")
|
|
async def get_band_profile(slug: str, session: Session = Depends(get_session)):
|
|
"""Get comprehensive band profile including members and stats"""
|
|
vertical = session.exec(
|
|
select(Vertical).where(Vertical.slug == slug)
|
|
).first()
|
|
|
|
if not vertical:
|
|
raise HTTPException(status_code=404, detail="Band not found")
|
|
|
|
# Get members via BandMembership if primary_artist_id exists
|
|
current_members = []
|
|
past_members = []
|
|
|
|
if vertical.primary_artist_id:
|
|
# Get all memberships for this band's artist
|
|
memberships = session.exec(
|
|
select(BandMembership, Musician)
|
|
.join(Musician, BandMembership.musician_id == Musician.id)
|
|
.where(BandMembership.artist_id == vertical.primary_artist_id)
|
|
.order_by(BandMembership.start_date)
|
|
).all()
|
|
|
|
for membership, musician in memberships:
|
|
member_data = {
|
|
"id": musician.id,
|
|
"name": musician.name,
|
|
"slug": musician.slug,
|
|
"image_url": musician.image_url,
|
|
"role": membership.role,
|
|
"primary_instrument": musician.primary_instrument,
|
|
"start_date": membership.start_date,
|
|
"end_date": membership.end_date,
|
|
"notes": membership.notes,
|
|
}
|
|
if membership.end_date is None:
|
|
current_members.append(member_data)
|
|
else:
|
|
past_members.append(member_data)
|
|
|
|
# Get stats
|
|
show_count = session.exec(
|
|
select(func.count(Show.id)).where(Show.vertical_id == vertical.id)
|
|
).one()
|
|
|
|
song_count = session.exec(
|
|
select(func.count(Song.id)).where(Song.vertical_id == vertical.id)
|
|
).one()
|
|
|
|
# Get venue count (distinct venues from shows)
|
|
venue_count = session.exec(
|
|
select(func.count(func.distinct(Show.venue_id)))
|
|
.where(Show.vertical_id == vertical.id)
|
|
).one()
|
|
|
|
# Get first and last show dates
|
|
first_show = session.exec(
|
|
select(Show.date)
|
|
.where(Show.vertical_id == vertical.id)
|
|
.order_by(Show.date.asc())
|
|
.limit(1)
|
|
).first()
|
|
|
|
last_show = session.exec(
|
|
select(Show.date)
|
|
.where(Show.vertical_id == vertical.id)
|
|
.order_by(Show.date.desc())
|
|
.limit(1)
|
|
).first()
|
|
|
|
stats = {
|
|
"total_shows": show_count,
|
|
"total_songs": song_count,
|
|
"total_venues": venue_count,
|
|
"first_show": first_show,
|
|
"last_show": last_show,
|
|
}
|
|
|
|
return {
|
|
"band": vertical,
|
|
"current_members": current_members,
|
|
"past_members": past_members,
|
|
"stats": stats,
|
|
}
|