Files
azionelab/backend/shows/models.py

86 lines
2.8 KiB
Python

from django.db import models
from django.db.models import F, Q, Sum
class TimeStampedModel(models.Model):
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
abstract = True
class Show(TimeStampedModel):
title = models.CharField(max_length=200)
slug = models.SlugField(max_length=220, unique=True)
summary = models.TextField(blank=True)
description = models.TextField(blank=True)
poster_image = models.URLField(blank=True)
is_published = models.BooleanField(default=False, db_index=True)
class Meta:
ordering = ["title"]
indexes = [
models.Index(fields=["slug"]),
models.Index(fields=["is_published"]),
]
def __str__(self):
return self.title
class Venue(TimeStampedModel):
name = models.CharField(max_length=200)
slug = models.SlugField(max_length=220, unique=True)
address = models.CharField(max_length=255)
city = models.CharField(max_length=120)
notes = models.TextField(blank=True)
class Meta:
ordering = ["name"]
indexes = [
models.Index(fields=["slug"]),
models.Index(fields=["city"]),
]
def __str__(self):
return self.name
class Performance(TimeStampedModel):
show = models.ForeignKey(Show, on_delete=models.PROTECT, related_name="performances")
venue = models.ForeignKey(Venue, on_delete=models.PROTECT, related_name="performances")
starts_at = models.DateTimeField(db_index=True)
room_capacity = models.PositiveIntegerField()
manually_occupied_seats = models.PositiveIntegerField(default=0)
additional_seats = models.PositiveIntegerField(default=0)
is_booking_enabled = models.BooleanField(default=True, db_index=True)
class Meta:
ordering = ["starts_at"]
indexes = [
models.Index(fields=["show", "starts_at"]),
models.Index(fields=["venue", "starts_at"]),
models.Index(fields=["is_booking_enabled", "starts_at"]),
]
constraints = [
models.CheckConstraint(
condition=Q(manually_occupied_seats__lte=F("room_capacity") + F("additional_seats")),
name="performance_manual_seats_within_capacity",
),
]
def __str__(self):
return f"{self.show} at {self.starts_at:%Y-%m-%d %H:%M}"
@property
def configured_capacity(self):
return self.room_capacity + self.additional_seats - self.manually_occupied_seats
def confirmed_seats(self):
result = self.reservations.filter(status="confirmed").aggregate(total=Sum("party_size"))
return result["total"] or 0
def available_seats(self):
return self.configured_capacity - self.confirmed_seats()