idorderbook da cui pescare il ticket * - new_schedule_id (int) -> idserviceschedule dello slot scelto * * Logica: * 1. Verifica che l'ordine sia dell'utente e abbia ticket residui. * 2. Verifica che lo slot esista e sia compatibile col servizio dell'ordine. * 3. Verifica posto libero e non-già-prenotato. * 4. Inserisce bookingclass status 'pending' (come bookandgo.php). * -------------------------------------------------------------------------- */ require_once __DIR__ . '/_bootstrap.php'; $userId = (int) $user->id; // ========================================================================== // INPUT // ========================================================================== $raw = file_get_contents('php://input'); $json = json_decode($raw, true); if (is_array($json)) { $orderId = (int) ($json['order_id'] ?? 0); $newScheduleId = (int) ($json['new_schedule_id'] ?? 0); } else { $orderId = (int) ($_POST['order_id'] ?? 0); $newScheduleId = (int) ($_POST['new_schedule_id'] ?? 0); } if ($orderId <= 0 || $newScheduleId <= 0) { http_response_code(400); echo json_encode(['success' => false, 'error' => 'Parametri mancanti']); exit; } // ========================================================================== // 1) Ordine dell'utente + ticket residui // ========================================================================== $stmt = $db->prepare(" SELECT idorderbook, iduser, idservice, nticket, expireon FROM orderbook WHERE idorderbook = :oid AND iduser = :uid LIMIT 1 "); $stmt->execute([':oid' => $orderId, ':uid' => $userId]); $order = $stmt->fetch(); if (!$order) { http_response_code(404); echo json_encode(['success' => false, 'error' => 'Ordine non trovato']); exit; } $orderServiceId = (int) $order['idservice']; $nticket = (int) ($order['nticket'] ?? 0); $expireon = $order['expireon'] ?? null; // Scadenza ordine if ($expireon !== null && $expireon < date('Y-m-d')) { http_response_code(409); echo json_encode([ 'success' => false, 'error' => 'Questo pacchetto è scaduto.', 'code' => 'expired', ]); exit; } // Calcolo ticket residui: nticket - (prenotazioni non cancellate su questo ordine) $stmt = $db->prepare(" SELECT COUNT(*) AS n FROM bookingclass WHERE idorder = :oid AND iduser = :uid AND status != 'cancelled' "); $stmt->execute([':oid' => $orderId, ':uid' => $userId]); $used = (int) ($stmt->fetch()['n'] ?? 0); $residui = $nticket - $used; if ($residui <= 0) { http_response_code(409); echo json_encode([ 'success' => false, 'error' => 'Non hai lezioni residue su questo pacchetto.', 'code' => 'no_tickets', ]); exit; } // ========================================================================== // 2) Slot esiste + compatibile col servizio dell'ordine // ========================================================================== $stmt = $db->prepare(" SELECT ss.idserviceschedule, ss.idservice, ss.dateschedule, s.maxcapacity FROM serviceschedule ss LEFT JOIN service s ON ss.idservice = s.idservice WHERE ss.idserviceschedule = :sched LIMIT 1 "); $stmt->execute([':sched' => $newScheduleId]); $slot = $stmt->fetch(); if (!$slot) { http_response_code(404); echo json_encode(['success' => false, 'error' => 'Slot non trovato']); exit; } $newServiceId = (int) $slot['idservice']; $newTime = $slot['dateschedule']; $maxCap = (int) ($slot['maxcapacity'] ?? 0); $compatible = [$orderServiceId]; $cs = $db->prepare("SELECT idassociateservice FROM associateclass WHERE idmainservice = :sid"); $cs->execute([':sid' => $orderServiceId]); foreach ($cs->fetchAll() as $r) { $compatible[] = (int) $r['idassociateservice']; } if (!in_array($newServiceId, $compatible, true)) { http_response_code(409); echo json_encode([ 'success' => false, 'error' => 'Lo slot scelto non è compatibile con questo pacchetto.', 'code' => 'not_compatible', ]); exit; } // ========================================================================== // 3) Posto libero + non già prenotato // ========================================================================== $stmt = $db->prepare(" SELECT COUNT(*) AS n FROM bookingclass WHERE idserviceschedule = :sched AND status = 'booked' "); $stmt->execute([':sched' => $newScheduleId]); $bookedCount = (int) ($stmt->fetch()['n'] ?? 0); if ($maxCap > 0 && $bookedCount >= $maxCap) { http_response_code(409); echo json_encode(['success' => false, 'error' => 'La classe scelta è piena.', 'code' => 'full']); exit; } $stmt = $db->prepare(" SELECT COUNT(*) AS n FROM bookingclass WHERE idserviceschedule = :sched AND iduser = :uid AND status IN ('booked','pending') "); $stmt->execute([':sched' => $newScheduleId, ':uid' => $userId]); if (((int) ($stmt->fetch()['n'] ?? 0)) > 0) { http_response_code(409); echo json_encode(['success' => false, 'error' => 'Sei già prenotato/a su questa classe.', 'code' => 'already_booked']); exit; } // ========================================================================== // 4) Inserimento (status pending, come bookandgo.php) // ========================================================================== try { $ins = $db->prepare(" INSERT INTO bookingclass (idserviceschedule, iduser, prevbookingstart, idprevserviceschedule, idservice, idorder, bookingstart, status) VALUES (:sched, :uid, NULL, 0, :service, :order, :newstart, 'pending') "); $ins->execute([ ':sched' => $newScheduleId, ':uid' => $userId, ':service' => $newServiceId, ':order' => $orderId, ':newstart' => $newTime, ]); } catch (Throwable $e) { http_response_code(500); echo json_encode(['success' => false, 'error' => 'Errore durante la prenotazione']); exit; } // ========================================================================== // OUTPUT // ========================================================================== echo json_encode([ 'success' => true, 'message' => 'Prenotazione richiesta. In attesa di conferma.', 'new_datetime' => $newTime, ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);