From 45c432916adf22ad683f39ced27ca8932b358545 Mon Sep 17 00:00:00 2001 From: solocla Date: Wed, 14 Oct 2026 14:55:18 +0200 Subject: [PATCH] fixed cancel lesson --- public/admin_cancel_booking.php | 172 ++++++++++++++++++++++++++++++++ public/situationusers.php | 77 +++++++++----- 2 files changed, 224 insertions(+), 25 deletions(-) create mode 100644 public/admin_cancel_booking.php diff --git a/public/admin_cancel_booking.php b/public/admin_cancel_booking.php new file mode 100644 index 0000000..ca77a87 --- /dev/null +++ b/public/admin_cancel_booking.php @@ -0,0 +1,172 @@ + 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) . "

+
"; + $mail->AltBody = "Ciao " . ($nome !== '' ? $nome : 'Yogi') . ",\n" + . "ti confermiamo che la tua lezione è stata cancellata.\n" + . "Lezione: {$className}\nData/ora: {$dateTxt}\n\n{$fromName}"; + + $mail->send(); + $emailNote = ' Email di conferma inviata.'; + } catch (Throwable $e) { + error_log("admin_cancel_booking #{$id}: email non inviata: " . $e->getMessage()); + $emailNote = ' Attenzione: la lezione è stata cancellata ma l\'email non è partita.'; + } + } +} + +$reprogNote = $incremented === 'Y' ? ' Conteggiata come riprogrammazione.' : ''; + +jsonOut(['success' => true, 'message' => 'Lezione cancellata.' . $reprogNote . $emailNote]); diff --git a/public/situationusers.php b/public/situationusers.php index d130681..1c05cb6 100644 --- a/public/situationusers.php +++ b/public/situationusers.php @@ -617,7 +617,8 @@ Ti ringraziamo per la collaborazione e per l’attenzione alla sicurezza di tutt actionTd.append($('