from django.db import transaction from django.db.models import F from .models import Reservation, Workshop class SoldOut(ValueError): pass def reserve(*, workshop_id, user, seats): if not isinstance(seats, int) or isinstance(seats, bool) or not 1 <= seats <= 4: raise ValueError("Seats must be an integer from one to four") with transaction.atomic(): changed = Workshop.objects.filter(pk=workshop_id, published=True, remaining__gte=seats).update(remaining=F("remaining") - seats) if changed != 1: raise SoldOut("Not enough seats") return Reservation.objects.create(workshop_id=workshop_id, user=user, seats=seats) def cancel(*, reservation_id, user): with transaction.atomic(): record = Reservation.objects.filter(pk=reservation_id, user=user).first() if record is None: return False count, _ = Reservation.objects.filter(pk=record.pk, user=user).delete() if count: Workshop.objects.filter(pk=record.workshop_id).update(remaining=F("remaining") + record.seats) return bool(count)