$msg]); exit; } $idbookingclass = isset($_POST['idbookingclass']) ? (int) $_POST['idbookingclass'] : 0; $idnewschedule = isset($_POST['idserviceschedule']) ? (int) $_POST['idserviceschedule'] : 0; $flagReprogrammed = (isset($_POST['is_reprogrammed']) && $_POST['is_reprogrammed'] === 'Y') ? 'Y' : 'N'; if ($idbookingclass <= 0 || $idnewschedule <= 0) { fail('Dati mancanti per la riprogrammazione.'); } $pdo = DBHandlerSelect::getInstance()->getConnection(); try { $pdo->beginTransaction(); // Prenotazione corrente (lock per evitare doppie riprogrammazioni concorrenti) $stmt = $pdo->prepare( "SELECT idbookingclass, idserviceschedule, bookingstart, idorder, iduser FROM bookingclass WHERE idbookingclass = :id FOR UPDATE" ); $stmt->execute([':id' => $idbookingclass]); $booking = $stmt->fetch(); if (!$booking) { $pdo->rollBack(); fail('Prenotazione non trovata.', 404); } // Classe destinazione $stmt = $pdo->prepare( "SELECT idserviceschedule, idservice, dateschedule FROM serviceschedule WHERE idserviceschedule = :id" ); $stmt->execute([':id' => $idnewschedule]); $newSchedule = $stmt->fetch(); if (!$newSchedule) { $pdo->rollBack(); fail('Classe di destinazione non trovata.', 404); } // Nessun senso spostare sulla stessa classe if ((int) $booking['idserviceschedule'] === $idnewschedule) { $pdo->rollBack(); fail('La classe di destinazione coincide con quella attuale.'); } // Anti-duplicato: l'utente e gia prenotato (attivo) nella classe destinazione? $dupStmt = $pdo->prepare( "SELECT COUNT(*) FROM bookingclass WHERE idserviceschedule = :newsched AND iduser = :iduser AND status = 'booked' AND idbookingclass <> :id" ); $dupStmt->execute([ ':newsched' => $idnewschedule, ':iduser' => (int) $booking['iduser'], ':id' => $idbookingclass, ]); if ((int) $dupStmt->fetchColumn() > 0) { $pdo->rollBack(); fail('L\'allieva e gia prenotata in questa classe.', 409); } // Valori precedenti da conservare $prevSchedule = $booking['idserviceschedule']; // puo essere NULL $prevStart = $booking['bookingstart']; // Aggiorna la prenotazione in place $upd = $pdo->prepare( "UPDATE bookingclass SET idserviceschedule = :newsched, idservice = :newservice, bookingstart = :newstart, idprevserviceschedule = :prevsched, prevbookingstart = :prevstart, is_reprogrammed = 'Y', status = 'booked' WHERE idbookingclass = :id" ); $upd->execute([ ':newsched' => $newSchedule['idserviceschedule'], ':newservice' => $newSchedule['idservice'], ':newstart' => $newSchedule['dateschedule'], ':prevsched' => $prevSchedule, ':prevstart' => $prevStart, ':id' => $idbookingclass, ]); // Incrementa il contatore riprogrammazioni sull'ordine, se richiesto e possibile $idorder = $booking['idorder'] !== null ? (int) $booking['idorder'] : 0; if ($flagReprogrammed === 'Y' && $idorder > 0) { $incr = $pdo->prepare( "UPDATE orderbook SET reprogrammed = reprogrammed + 1 WHERE idorderbook = :idorder" ); $incr->execute([':idorder' => $idorder]); } $pdo->commit(); echo json_encode(['success' => true]); } catch (Throwable $ex) { if ($pdo->inTransaction()) { $pdo->rollBack(); } fail('Errore durante la riprogrammazione: ' . $ex->getMessage(), 500); }