Merge branch 'fix/checkin-frontend-url' into develop

This commit is contained in:
2026-04-30 11:01:18 +02:00
5 changed files with 17 additions and 10 deletions

View File

@@ -7,11 +7,11 @@ from django.conf import settings
from .models import Reservation from .models import Reservation
CHECK_IN_PREVIEW_PATH = "/api/check-ins/preview/" CHECK_IN_PAGE_PATH = "/check-in"
def build_check_in_preview_url(raw_check_in_token): def build_check_in_preview_url(raw_check_in_token):
return f"{settings.SITE_BASE_URL}{CHECK_IN_PREVIEW_PATH}?token={raw_check_in_token}" return f"{settings.SITE_BASE_URL}{CHECK_IN_PAGE_PATH}?token={raw_check_in_token}"
def generate_check_in_qr_png(raw_check_in_token): def generate_check_in_qr_png(raw_check_in_token):

View File

@@ -134,7 +134,7 @@ class ReservationAdminTests(TestCase):
self.assertEqual(reservation.status, Reservation.Status.CONFIRMED) self.assertEqual(reservation.status, Reservation.Status.CONFIRMED)
self.assertIsNotNone(confirmation_token.used_at) self.assertIsNotNone(confirmation_token.used_at)
self.assertContains(response, "Reservation confirmed manually") self.assertContains(response, "Reservation confirmed manually")
self.assertContains(response, "/api/check-ins/preview/?token=") self.assertContains(response, "/check-in?token=")
self.assertTrue( self.assertTrue(
ReservationToken.objects.filter( ReservationToken.objects.filter(
reservation=reservation, reservation=reservation,

View File

@@ -165,7 +165,7 @@ class BookingApiTests(APITestCase):
self.assertEqual(response.data["party_size"], reservation.party_size) self.assertEqual(response.data["party_size"], reservation.party_size)
self.assertTrue( self.assertTrue(
response.data["qr_code_url"].startswith( response.data["qr_code_url"].startswith(
"https://tickets.azionelab.example/api/check-ins/preview/?token=" "https://tickets.azionelab.example/check-in?token="
) )
) )
self.assertNotIn(raw_token, response.data["qr_code_url"]) self.assertNotIn(raw_token, response.data["qr_code_url"])
@@ -257,7 +257,7 @@ class BookingApiTests(APITestCase):
self.assertEqual(response.data["reservation_id"], reservation.id) self.assertEqual(response.data["reservation_id"], reservation.id)
self.assertTrue( self.assertTrue(
response.data["qr_code_url"].startswith( response.data["qr_code_url"].startswith(
"https://tickets.azionelab.example/api/check-ins/preview/?token=" "https://tickets.azionelab.example/check-in?token="
) )
) )
self.assertTrue(response.data["qr_code_image"].startswith("data:image/png;base64,")) self.assertTrue(response.data["qr_code_image"].startswith("data:image/png;base64,"))

View File

@@ -247,7 +247,7 @@ class BookingServiceTests(TestCase):
) )
self.assertTrue( self.assertTrue(
result.qr_code_url.startswith( result.qr_code_url.startswith(
"https://tickets.azionelab.example/api/check-ins/preview/?token=" "https://tickets.azionelab.example/check-in?token="
) )
) )
self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,")) self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,"))
@@ -282,7 +282,7 @@ class BookingServiceTests(TestCase):
self.assertGreater(len(qr_code_image), len("data:image/png;base64,")) self.assertGreater(len(qr_code_image), len("data:image/png;base64,"))
self.assertEqual( self.assertEqual(
build_check_in_preview_url(raw_check_in_token), build_check_in_preview_url(raw_check_in_token),
"https://tickets.azionelab.example/api/check-ins/preview/?token=opaque-check-in-token", "https://tickets.azionelab.example/check-in?token=opaque-check-in-token",
) )
def test_qr_code_is_not_generated_for_pending_reservation(self): def test_qr_code_is_not_generated_for_pending_reservation(self):
@@ -430,7 +430,7 @@ class BookingServiceTests(TestCase):
self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN) self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN)
self.assertTrue( self.assertTrue(
result.qr_code_url.startswith( result.qr_code_url.startswith(
"https://tickets.azionelab.example/api/check-ins/preview/?token=" "https://tickets.azionelab.example/check-in?token="
) )
) )
@@ -462,7 +462,7 @@ class BookingServiceTests(TestCase):
self.assertEqual(result.reservation, reservation) self.assertEqual(result.reservation, reservation)
self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN) self.assertEqual(result.check_in_token.purpose, ReservationToken.Purpose.CHECK_IN)
self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,")) self.assertTrue(result.qr_code_image.startswith("data:image/png;base64,"))
self.assertIn("/api/check-ins/preview/?token=", result.qr_code_url) self.assertIn("/check-in?token=", result.qr_code_url)
def create_reservation(self, **overrides): def create_reservation(self, **overrides):
data = { data = {

View File

@@ -11,7 +11,7 @@ import {
} from '@angular/core'; } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms'; import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { RouterLink } from '@angular/router'; import { ActivatedRoute, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card'; import { MatCardModule } from '@angular/material/card';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
@@ -326,6 +326,7 @@ type BarcodeDetectorConstructor = new (options?: { formats?: string[] }) => Barc
export class CheckInPlaceholderPageComponent { export class CheckInPlaceholderPageComponent {
private readonly destroyRef = inject(DestroyRef); private readonly destroyRef = inject(DestroyRef);
private readonly formBuilder = inject(FormBuilder); private readonly formBuilder = inject(FormBuilder);
private readonly route = inject(ActivatedRoute);
private readonly showsApi = inject(ShowsApiService); private readonly showsApi = inject(ShowsApiService);
private readonly barcodeDetectorCtor = (globalThis as { BarcodeDetector?: BarcodeDetectorConstructor }).BarcodeDetector; private readonly barcodeDetectorCtor = (globalThis as { BarcodeDetector?: BarcodeDetectorConstructor }).BarcodeDetector;
private readonly scannerSupported = private readonly scannerSupported =
@@ -358,6 +359,12 @@ export class CheckInPlaceholderPageComponent {
constructor() { constructor() {
this.destroyRef.onDestroy(() => this.stopScanner()); this.destroyRef.onDestroy(() => this.stopScanner());
const tokenFromQuery = this.route.snapshot.queryParamMap.get('token')?.trim() ?? '';
if (tokenFromQuery) {
this.tokenForm.controls.token.setValue(tokenFromQuery);
this.tokenForm.controls.token.markAsTouched();
this.preview();
}
} }
protected preview(): void { protected preview(): void {