&schedule_id=&is_reprogrammed= * * Regole (identiche alla webapp): * - status resta 'booked', lostlesson non toccato * - is_reprogrammed sulla prenotazione va sempre a 'Y' * - orderbook.reprogrammed +1 solo se flag='Y' e idorder valido * -------------------------------------------------------------------------- */ require_once __DIR__ . '/_bootstrap.php'; // Gate staff $roleId = (int) $user->role_id; if (!in_array($roleId, [1, 3], true)) { http_response_code(403); echo json_encode(['success' => false, 'message' => 'Forbidden']); exit; } $bookingId = isset($_POST['booking_id']) ? (int) $_POST['booking_id'] : 0; $newSchedId = isset($_POST['schedule_id']) ? (int) $_POST['schedule_id'] : 0; $flagReprogrammed = (isset($_POST['is_reprogrammed']) && $_POST['is_reprogrammed'] === 'Y') ? 'Y' : 'N'; if ($bookingId <= 0 || $newSchedId <= 0) { http_response_code(400); echo json_encode(['success' => false, 'message' => 'Dati mancanti']); exit; } try { $db->beginTransaction(); // Prenotazione corrente (lock) $stmt = $db->prepare( "SELECT idbookingclass, idserviceschedule, bookingstart, idorder, iduser FROM bookingclass WHERE idbookingclass = :id FOR UPDATE" ); $stmt->execute([':id' => $bookingId]); $booking = $stmt->fetch(PDO::FETCH_ASSOC); if (!$booking) { $db->rollBack(); http_response_code(404); echo json_encode(['success' => false, 'message' => 'Prenotazione non trovata']); exit; } // Classe destinazione $stmt = $db->prepare( "SELECT idserviceschedule, idservice, dateschedule FROM serviceschedule WHERE idserviceschedule = :id" ); $stmt->execute([':id' => $newSchedId]); $newSchedule = $stmt->fetch(PDO::FETCH_ASSOC); if (!$newSchedule) { $db->rollBack(); http_response_code(404); echo json_encode(['success' => false, 'message' => 'Classe destinazione non trovata']); exit; } // Stessa classe: niente da fare if ((int) $booking['idserviceschedule'] === $newSchedId) { $db->rollBack(); http_response_code(400); echo json_encode(['success' => false, 'message' => 'Classe destinazione uguale a quella attuale']); exit; } // Anti-duplicato: già prenotato (attivo) nella destinazione? $dup = $db->prepare( "SELECT COUNT(*) FROM bookingclass WHERE idserviceschedule = :newsched AND iduser = :iduser AND status = 'booked' AND idbookingclass <> :id" ); $dup->execute([ ':newsched' => $newSchedId, ':iduser' => (int) $booking['iduser'], ':id' => $bookingId, ]); if ((int) $dup->fetchColumn() > 0) { $db->rollBack(); http_response_code(409); echo json_encode(['success' => false, 'message' => 'Allievo già prenotato in questa classe']); exit; } // Valori precedenti da conservare $prevSchedule = $booking['idserviceschedule']; $prevStart = $booking['bookingstart']; // Aggiorna in place $upd = $db->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' => (int) $newSchedule['idserviceschedule'], ':newservice' => (int) $newSchedule['idservice'], ':newstart' => $newSchedule['dateschedule'], ':prevsched' => $prevSchedule, ':prevstart' => $prevStart, ':id' => $bookingId, ]); // Incrementa contatore riprogrammazioni se richiesto e possibile $idorder = $booking['idorder'] !== null ? (int) $booking['idorder'] : 0; if ($flagReprogrammed === 'Y' && $idorder > 0) { $incr = $db->prepare( "UPDATE orderbook SET reprogrammed = reprogrammed + 1 WHERE idorderbook = :idorder" ); $incr->execute([':idorder' => $idorder]); } $db->commit(); echo json_encode([ 'success' => true, 'booking_id' => $bookingId, 'schedule_id' => $newSchedId, 'reprogrammed_counted' => ($flagReprogrammed === 'Y' && $idorder > 0), ], JSON_UNESCAPED_UNICODE); } catch (Throwable $ex) { if ($db->inTransaction()) { $db->rollBack(); } error_log('api_teacher_reprogram error: ' . $ex->getMessage()); http_response_code(500); echo json_encode(['success' => false, 'message' => 'Errore riprogrammazione']); }