126 lines
4.4 KiB
Python
126 lines
4.4 KiB
Python
from sqlalchemy import select
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.core.errors import AppError
|
|
from app.models.catalog import Event, TicketType, Venue
|
|
from app.models.enums import TicketTypeStatus
|
|
from app.schemas.admin import (
|
|
EventCreate,
|
|
EventUpdate,
|
|
TicketTypeCreate,
|
|
TicketTypeUpdate,
|
|
VenueCreate,
|
|
VenueUpdate,
|
|
)
|
|
|
|
|
|
def list_venues_admin(db: Session) -> list[Venue]:
|
|
return list(db.scalars(select(Venue).order_by(Venue.name.asc())).all())
|
|
|
|
|
|
def create_venue(db: Session, body: VenueCreate) -> Venue:
|
|
if db.scalar(select(Venue.id).where(Venue.slug == body.slug)):
|
|
raise AppError("Venue slug already exists", status_code=409)
|
|
venue = Venue(**body.model_dump())
|
|
db.add(venue)
|
|
db.commit()
|
|
db.refresh(venue)
|
|
return venue
|
|
|
|
|
|
def update_venue(db: Session, venue_id: int, body: VenueUpdate) -> Venue:
|
|
venue = db.get(Venue, venue_id)
|
|
if not venue:
|
|
raise AppError("Venue not found", status_code=404)
|
|
data = body.model_dump(exclude_unset=True)
|
|
if "slug" in data and data["slug"] != venue.slug:
|
|
if db.scalar(select(Venue.id).where(Venue.slug == data["slug"])):
|
|
raise AppError("Venue slug already exists", status_code=409)
|
|
for key, value in data.items():
|
|
setattr(venue, key, value)
|
|
db.commit()
|
|
db.refresh(venue)
|
|
return venue
|
|
|
|
|
|
def list_events_admin(db: Session) -> list[Event]:
|
|
return list(db.scalars(select(Event).order_by(Event.starts_at.desc())).all())
|
|
|
|
|
|
def create_event(db: Session, body: EventCreate) -> Event:
|
|
if not db.get(Venue, body.venue_id):
|
|
raise AppError("Venue not found", status_code=400)
|
|
if db.scalar(select(Event.id).where(Event.slug == body.slug)):
|
|
raise AppError("Event slug already exists", status_code=409)
|
|
event = Event(**body.model_dump())
|
|
db.add(event)
|
|
db.commit()
|
|
db.refresh(event)
|
|
return event
|
|
|
|
|
|
def update_event(db: Session, event_id: int, body: EventUpdate) -> Event:
|
|
event = db.get(Event, event_id)
|
|
if not event:
|
|
raise AppError("Event not found", status_code=404)
|
|
data = body.model_dump(exclude_unset=True)
|
|
if "venue_id" in data and not db.get(Venue, data["venue_id"]):
|
|
raise AppError("Venue not found", status_code=400)
|
|
if "slug" in data and data["slug"] != event.slug:
|
|
if db.scalar(select(Event.id).where(Event.slug == data["slug"])):
|
|
raise AppError("Event slug already exists", status_code=409)
|
|
for key, value in data.items():
|
|
setattr(event, key, value)
|
|
db.commit()
|
|
db.refresh(event)
|
|
return event
|
|
|
|
|
|
def ticket_type_to_admin(tier: TicketType) -> dict:
|
|
return {
|
|
"id": tier.id,
|
|
"event_id": tier.event_id,
|
|
"name": tier.name,
|
|
"description": tier.description,
|
|
"price_paise": tier.price_paise,
|
|
"quantity_total": tier.quantity_total,
|
|
"quantity_sold": tier.quantity_sold,
|
|
"remaining": max(tier.quantity_total - tier.quantity_sold, 0),
|
|
"status": tier.status,
|
|
"sort_order": tier.sort_order,
|
|
}
|
|
|
|
|
|
def list_ticket_types(db: Session, event_id: int | None = None) -> list[dict]:
|
|
query = select(TicketType).order_by(TicketType.event_id.asc(), TicketType.sort_order.asc())
|
|
if event_id is not None:
|
|
query = query.where(TicketType.event_id == event_id)
|
|
return [ticket_type_to_admin(row) for row in db.scalars(query).all()]
|
|
|
|
|
|
def create_ticket_type(db: Session, body: TicketTypeCreate) -> TicketType:
|
|
if not db.get(Event, body.event_id):
|
|
raise AppError("Event not found", status_code=400)
|
|
tier = TicketType(**body.model_dump())
|
|
db.add(tier)
|
|
db.commit()
|
|
db.refresh(tier)
|
|
return tier
|
|
|
|
|
|
def update_ticket_type(db: Session, tier_id: int, body: TicketTypeUpdate) -> TicketType:
|
|
tier = db.get(TicketType, tier_id)
|
|
if not tier:
|
|
raise AppError("Ticket type not found", status_code=404)
|
|
data = body.model_dump(exclude_unset=True)
|
|
if "quantity_total" in data and data["quantity_total"] < tier.quantity_sold:
|
|
raise AppError("Total quantity cannot be less than sold count", status_code=400)
|
|
for key, value in data.items():
|
|
setattr(tier, key, value)
|
|
if tier.quantity_sold >= tier.quantity_total:
|
|
tier.status = TicketTypeStatus.sold_out
|
|
elif tier.status == TicketTypeStatus.sold_out and tier.quantity_sold < tier.quantity_total:
|
|
tier.status = TicketTypeStatus.active
|
|
db.commit()
|
|
db.refresh(tier)
|
|
return tier
|