false, 'message' => 'Metodo non consentito.'], 405); } $id = (int) ($_POST['id'] ?? 0); $sendEmail = ($_POST['send_email'] ?? 'N') === 'Y'; $countReprog = ($_POST['count_reprog'] ?? 'N') === 'Y'; $staffId = (int) $iduserlogin; // chi cancella: sempre l'utente della sessione if ($id <= 0) { jsonOut(['success' => false, 'message' => 'Prenotazione non valida.'], 400); } $pdo = DBHandlerSelect::getInstance()->getConnection(); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $bk = null; $incremented = 'N'; try { $pdo->beginTransaction(); // Prenotazione + dati per l'email, riga bloccata contro doppi click $st = $pdo->prepare(" SELECT bc.idbookingclass, bc.idorder, bc.bookingstart, s.servicename, ss.dateschedule, u.email, u.first_name FROM bookingclass bc LEFT JOIN service s ON s.idservice = bc.idservice LEFT JOIN serviceschedule ss ON ss.idserviceschedule = bc.idserviceschedule LEFT JOIN auth_users u ON u.id = bc.iduser WHERE bc.idbookingclass = ? FOR UPDATE "); $st->execute([$id]); $bk = $st->fetch(PDO::FETCH_ASSOC); if (!$bk) { throw new RuntimeException('notfound'); } // Conta come riprogrammazione (solo se c'è un ordine collegato) if ($countReprog && $bk['idorder'] !== null) { $up = $pdo->prepare("UPDATE orderbook SET reprogrammed = reprogrammed + 1 WHERE idorderbook = ?"); $up->execute([(int) $bk['idorder']]); if ($up->rowCount() === 1) { $incremented = 'Y'; } } // Copia nello storico $ins = $pdo->prepare(" INSERT INTO bookingclass_cancellations (idbookingclass, idserviceschedule, bookingstart, status, idservice, iduser, idorder, prevbookingstart, is_reprogrammed, is_gift, booking_created_at, cancelled_at, cancelled_by, reprogrammed_incremented) SELECT idbookingclass, idserviceschedule, bookingstart, status, idservice, iduser, idorder, prevbookingstart, is_reprogrammed, is_gift, created_at, NOW(), ?, ? FROM bookingclass WHERE idbookingclass = ? "); $ins->execute([$staffId, $incremented, $id]); // Eliminazione $del = $pdo->prepare("DELETE FROM bookingclass WHERE idbookingclass = ?"); $del->execute([$id]); $pdo->commit(); } catch (PDOException $e) { if ($pdo->inTransaction()) $pdo->rollBack(); error_log("admin_cancel_booking #{$id} (staff #{$staffId}): " . $e->getMessage()); jsonOut(['success' => false, 'message' => 'Errore durante la cancellazione. Riprova.'], 500); } catch (RuntimeException $e) { if ($pdo->inTransaction()) $pdo->rollBack(); jsonOut(['success' => false, 'message' => 'Prenotazione non trovata (forse già cancellata).'], 404); } /* ------------------------------------------------------------------------- * Email di conferma (dopo il commit, solo se richiesta) * ---------------------------------------------------------------------- */ $emailNote = ''; if ($sendEmail) { $to = trim((string) ($bk['email'] ?? '')); if (!filter_var($to, FILTER_VALIDATE_EMAIL)) { $emailNote = ' Email non inviata: indirizzo dell\'allieva mancante o non valido.'; } else { try { require_once(__DIR__ . '/class/mailer.php'); $clean = fn($v) => trim((string) $v, "\" \t\n\r\0\x0B"); $enc = strtolower($clean($_ENV['MAIL_ENCRYPTION'] ?? 'ssl')); $mail = new \PHPMailer\PHPMailer\PHPMailer(true); $mail->isSMTP(); $mail->Host = $clean($_ENV['MAIL_HOST'] ?? ''); $mail->SMTPAuth = true; $mail->Username = $_ENV['MAIL_USERNAME'] ?? ''; $mail->Password = $_ENV['MAIL_PASSWORD'] ?? ''; $mail->Port = (int) ($_ENV['MAIL_PORT'] ?? 465); if (in_array($enc, ['tls', 'ssl'], true)) { $mail->SMTPSecure = $enc; } $mail->Timeout = 20; $mail->CharSet = 'UTF-8'; $fromName = $clean($_ENV['MAIL_FROM_NAME'] ?? 'YogiBook'); $mail->setFrom($clean($_ENV['MAIL_FROM_ADDRESS'] ?? ''), $fromName); $nome = trim((string) ($bk['first_name'] ?? '')); $className = $bk['servicename'] ?: 'Lezione'; $dateRaw = $bk['dateschedule'] ?: $bk['bookingstart']; $dateTxt = $dateRaw ? date('d/m/Y H:i', strtotime($dateRaw)) : ''; $h = fn($v) => htmlspecialchars((string) $v, ENT_QUOTES, 'UTF-8'); $mail->addAddress($to, $nome); $mail->isHTML(true); $mail->Subject = 'Lezione cancellata - ' . $className; $mail->Body = "
Ciao " . $h($nome !== '' ? $nome : 'Yogi') . ",
ti confermiamo che la tua lezione è stata cancellata.
Lezione: " . $h($className) . "
Data/ora: " . $h($dateTxt) . "
Se hai domande, rispondi pure a questa email.
A presto,
" . $h($fromName) . "