feat(admin): add manual reservation operations

This commit is contained in:
bisco
2026-04-29 23:47:22 +02:00
parent ffbe1a5b04
commit 7c90da5884
8 changed files with 507 additions and 26 deletions

View File

@@ -15,10 +15,13 @@ from bookings.services import (
ExpiredToken,
InvalidToken,
NotEnoughSeats,
ReservationNotConfirmed,
calculate_available_seats,
confirm_reservation_manually,
confirm_reservation_from_token,
create_pending_reservation,
generate_confirmation_token,
issue_check_in_access_for_reservation,
retrieve_reservation_qr_from_token,
)
from shows.models import Performance, Show, Venue
@@ -382,6 +385,54 @@ class BookingServiceTests(TestCase):
self.assertTrue(any("FOR UPDATE" in query["sql"] for query in queries))
@override_settings(SITE_BASE_URL="https://tickets.azionelab.example")
def test_manual_confirmation_reuses_capacity_rules_and_generates_check_in_access(self):
reservation = self.create_reservation()
confirmation_token, _ = generate_confirmation_token(reservation)
result = confirm_reservation_manually(reservation_id=reservation.id)
reservation.refresh_from_db()
confirmation_token.refresh_from_db()
self.assertEqual(reservation.status, Reservation.Status.CONFIRMED)
self.assertIsNotNone(confirmation_token.used_at)
self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN)
self.assertTrue(
result.qr_code_url.startswith(
"https://tickets.azionelab.example/api/check-ins/preview/?token="
)
)
def test_manual_confirmation_rejects_non_pending_reservation(self):
reservation = self.create_reservation(
status=Reservation.Status.CONFIRMED,
confirmed_at=timezone.now(),
)
with self.assertRaises(AlreadyConfirmedReservation):
confirm_reservation_manually(reservation_id=reservation.id)
@override_settings(SITE_BASE_URL="https://tickets.azionelab.example")
def test_issue_check_in_access_requires_confirmed_reservation(self):
reservation = self.create_reservation()
with self.assertRaises(ReservationNotConfirmed):
issue_check_in_access_for_reservation(reservation_id=reservation.id)
@override_settings(SITE_BASE_URL="https://tickets.azionelab.example")
def test_issue_check_in_access_generates_qr_for_confirmed_reservation(self):
reservation = self.create_reservation(
status=Reservation.Status.CONFIRMED,
confirmed_at=timezone.now(),
)
result = issue_check_in_access_for_reservation(reservation_id=reservation.id)
self.assertEqual(result.reservation, reservation)
self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN)
self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,"))
self.assertIn("/api/check-ins/preview/?token=", result.qr_code_url)
def create_reservation(self, **overrides):
data = {
"performance": self.performance,