60 lines
2.1 KiB
PHP
60 lines
2.1 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Lista d'attesa — promozione automatica.
|
|
*
|
|
* IMPORTANTE: chiamare DENTRO una transazione in cui la riga dell'evento è già
|
|
* bloccata (SELECT ... FOR UPDATE), tipicamente subito dopo aver liberato posti
|
|
* (cancellazione di una prenotazione confermata). Così due operazioni simultanee
|
|
* non promuovono oltre la capienza.
|
|
*
|
|
* Promuove in ordine di arrivo (FIFO) le prenotazioni 'waiting' che entrano nei
|
|
* posti liberi e si ferma alla prima che non ci sta, per rispettare la coda
|
|
* (non "salta" chi è davanti).
|
|
*
|
|
* @return array<int,array> le prenotazioni promosse (per inviare le email nello Step 4)
|
|
*/
|
|
if (!function_exists('promoteFromWaitlist')) {
|
|
function promoteFromWaitlist(PDO $pdo, int $eventId): array
|
|
{
|
|
$ev = $pdo->prepare("SELECT max_seats FROM events WHERE id = ?");
|
|
$ev->execute([$eventId]);
|
|
$maxSeats = (int) $ev->fetchColumn();
|
|
if ($maxSeats <= 0) {
|
|
return [];
|
|
}
|
|
|
|
$os = $pdo->prepare("SELECT COALESCE(SUM(seats),0) FROM event_bookings
|
|
WHERE event_id = ? AND status IN ('confirmed','pending')");
|
|
$os->execute([$eventId]);
|
|
$free = $maxSeats - (int) $os->fetchColumn();
|
|
if ($free <= 0) {
|
|
return [];
|
|
}
|
|
|
|
$ws = $pdo->prepare("SELECT * FROM event_bookings
|
|
WHERE event_id = ? AND status = 'waiting'
|
|
ORDER BY created_at ASC, id ASC");
|
|
$ws->execute([$eventId]);
|
|
$waiting = $ws->fetchAll(PDO::FETCH_ASSOC);
|
|
|
|
$promoted = [];
|
|
$upd = $pdo->prepare("UPDATE event_bookings SET status = 'confirmed', updated_at = NOW() WHERE id = ?");
|
|
foreach ($waiting as $w) {
|
|
$need = (int) $w['seats'];
|
|
if ($need <= $free) {
|
|
$upd->execute([$w['id']]);
|
|
$free -= $need;
|
|
$w['status'] = 'confirmed';
|
|
$promoted[] = $w;
|
|
if ($free <= 0) {
|
|
break;
|
|
}
|
|
} else {
|
|
break; // rispetta la coda
|
|
}
|
|
}
|
|
return $promoted;
|
|
}
|
|
}
|