Fix manage-booking time slots; align modify email with original

- getAvailableTimes() takes optional exclude_booking_id so a guest's
  own booking isn't counted as a conflict when editing — original time
  now reappears when extending services
- Manage-booking AJAX passes manage_token; server resolves to booking_id
- manage_booking_process uses the new param instead of the date-swap
  workaround (removes a small race-condition risk)
- Modify-booking emails (no/en/hu) now include Name/Email/Phone rows
  and the 24h cancellation policy, matching the original booking email
This commit is contained in:
Ubuntu
2026-05-10 13:18:07 +00:00
parent 1e32a146a7
commit e24e68f603
3 changed files with 68 additions and 26 deletions
+38 -14
View File
@@ -210,7 +210,12 @@ class Pages extends CI_Controller {
} }
if(isset($_POST['action']) && $_POST['action'] == 'getAvailableTimes' && isset($_POST['selectedDate'])){ if(isset($_POST['action']) && $_POST['action'] == 'getAvailableTimes' && isset($_POST['selectedDate'])){
$results = $this->Service_model->getAvailableTimes($_POST['worker_id'], $_POST['selectedDate'], $_POST['servicelength'].':00'); $excludeBookingId = null;
if(!empty($_POST['manage_token'])){
$existingBooking = $this->Service_model->getBookingByToken($_POST['manage_token']);
if($existingBooking) $excludeBookingId = $existingBooking->booking_id;
}
$results = $this->Service_model->getAvailableTimes($_POST['worker_id'], $_POST['selectedDate'], $_POST['servicelength'].':00', $excludeBookingId);
$rowIndex = 1; $rowIndex = 1;
if(!empty($results)){ if(!empty($results)){
@@ -820,10 +825,8 @@ class Pages extends CI_Controller {
return; return;
} }
// Slot availability (temporarily exclude current booking) // Slot availability (exclude current booking from conflict check)
$this->Service_model->updateBooking($booking->booking_id, ['booking_date' => '1970-01-01']); $available = $this->Service_model->getAvailableTimes($newWorkerId, $newBookingDate, $servicelength, $booking->booking_id);
$available = $this->Service_model->getAvailableTimes($newWorkerId, $newBookingDate, $servicelength);
$this->Service_model->updateBooking($booking->booking_id, ['booking_date' => $booking->booking_date]);
if(!is_array($available) || !in_array($newStartTime, $available)){ if(!is_array($available) || !in_array($newStartTime, $available)){
$this->output->set_status_header(409)->set_content_type('application/json') $this->output->set_status_header(409)->set_content_type('application/json')
@@ -921,40 +924,61 @@ class Pages extends CI_Controller {
$subject = '[studiobeve] Din bestilling er oppdatert'; $subject = '[studiobeve] Din bestilling er oppdatert';
$content = 'Kjære gjest,<br />Din bestilling er oppdatert.<br /><br />'; $content = 'Kjære gjest,<br />Din bestilling er oppdatert.<br /><br />';
$content .= '<table>'; $content .= '<table>';
$content .= '<tr><td>Navn: </td><td>'.$booking->guest_name.'</td></tr>';
$content .= '<tr><td>E-post: </td><td>'.$booking->guest_email.'</td></tr>';
$content .= '<tr><td>Telefon: </td><td>'.$booking->guest_phone.'</td></tr>';
$content .= '<tr><td>Arbeider: </td><td>'.$worker->worker_name.'</td></tr>'; $content .= '<tr><td>Arbeider: </td><td>'.$worker->worker_name.'</td></tr>';
$content .= '<tr><td>Dato: </td><td>'.$newBookingDate.'</td></tr>'; $content .= '<tr><td>Dato: </td><td>'.$newBookingDate.'</td></tr>';
$content .= '<tr><td>Tid: </td><td>'.$newStartTime.' - '.$finishTime.'</td></tr>'; $content .= '<tr><td>Tid: </td><td>'.$newStartTime.' - '.$finishTime.'</td></tr>';
$content .= '<tr><td>Tjenester: </td><td><table>'; $content .= '<tr><td>Tjenester: </td><td><table>';
foreach($serviceArray as $s){ $content .= '<tr><td>'.$s->service_name_no.'</td><td>'.$s->service_price.' kr</td></tr>'; } foreach($serviceArray as $s){ $content .= '<tr><td>'.$s->service_name_no.'</td><td>'.$s->service_price.' kr</td></tr>'; }
$content .= '</table></td><tr><td>Totalpris: </td><td><strong>'.$totalServicePrice.' kr</strong></td></tr></table>'; $content .= '</table></td>';
$content .= '<br /><br /><a href="'.$manageLink.'">Administrer bestilling</a>'; $content .= '<tr><td>Totalpris: </td><td><strong>'.$totalServicePrice.' kr</strong></td></tr>';
$content .= '<br /><br /> STUDIOBEVE'; $content .= '</table>';
$content .= '<br /><br /><a href="'.$manageLink.'">Administrer bestilling</a><br />';
$content .= '<br /> Dersom noe skulle dukke opp og du ikke kan komme til avtalen din, vennligst gi oss beskjed minst 24 timer i forveien, slik at vi kan gi timen videre til en annen kunde og våre kollegers tid ikke blir stående ubrukt; avbestillinger innen 24 timer, eller manglende oppmøte, vil bli belastet med full pris for behandlingen; avbestilling kan gjøres via e-post til <a href="mailto:info@studiobeve.no">info@studiobeve.no</a> eller ved å sende oss en melding på Instagram eller Facebook. Takk for forståelsen og samarbeidet!';
$content .= '<br />';
$content .= '<br /> STUDIOBEVE';
break; break;
case 'hu': case 'hu':
$subject = '[studiobeve] A foglalásod módosítva lett'; $subject = '[studiobeve] A foglalásod módosítva lett';
$content = 'Kedves Vendégünk,<br />A foglalásod módosítva lett.<br /><br />'; $content = 'Kedves Vendégünk,<br />A foglalásod módosítva lett.<br /><br />';
$content .= '<table>'; $content .= '<table>';
$content .= '<tr><td>Név: </td><td>'.$booking->guest_name.'</td></tr>';
$content .= '<tr><td>Email: </td><td>'.$booking->guest_email.'</td></tr>';
$content .= '<tr><td>Telefon: </td><td>'.$booking->guest_phone.'</td></tr>';
$content .= '<tr><td>Dolgozó: </td><td>'.$worker->worker_name.'</td></tr>'; $content .= '<tr><td>Dolgozó: </td><td>'.$worker->worker_name.'</td></tr>';
$content .= '<tr><td>Dátum: </td><td>'.$newBookingDate.'</td></tr>'; $content .= '<tr><td>Dátum: </td><td>'.$newBookingDate.'</td></tr>';
$content .= '<tr><td>Időpont: </td><td>'.$newStartTime.' - '.$finishTime.'</td></tr>'; $content .= '<tr><td>Időpont: </td><td>'.$newStartTime.' - '.$finishTime.'</td></tr>';
$content .= '<tr><td>Szolgáltatás(ok): </td><td><table>'; $content .= '<tr><td>Szolgáltatás(ok): </td><td><table>';
foreach($serviceArray as $s){ $content .= '<tr><td>'.$s->service_name_hu.'</td><td>'.$s->service_price.' kr</td></tr>'; } foreach($serviceArray as $s){ $content .= '<tr><td>'.$s->service_name_hu.'</td><td>'.$s->service_price.' kr</td></tr>'; }
$content .= '</table></td><tr><td>Összesen: </td><td><strong>'.$totalServicePrice.' kr</strong></td></tr></table>'; $content .= '</table></td>';
$content .= '<br /><br /><a href="'.$manageLink.'">Foglalás kezelése</a>'; $content .= '<tr><td>Összesen fizetendő: </td><td><strong>'.$totalServicePrice.' kr</strong></td></tr>';
$content .= '<br /><br /> STUDIOBEVE'; $content .= '</table>';
$content .= '<br /><br /><a href="'.$manageLink.'">Foglalás kezelése</a><br />';
$content .= '<br /> Kérünk, ha valami közbejön, és mégsem tudsz eljönni a lefoglalt időpontodra, jelezd nekünk legalább 24 órával előre, így más vendégnek is tudunk szabad időpontot biztosítani, és kollégáink ideje sem marad kihasználatlanul; 24 órán belüli lemondás, illetve meg nem jelenés esetén a szolgáltatás teljes díja felszámításra kerül; a lemondást az <a href="mailto:info@studiobeve.no">info@studiobeve.no</a> e-mail címen, vagy Instagram- és Facebook-üzenetben tudod megtenni. Köszönjük a megértést és az együttműködést!';
$content .= '<br />';
$content .= '<br /> STUDIOBEVE';
break; break;
default: default:
$subject = '[studiobeve] Your booking has been updated'; $subject = '[studiobeve] Your booking has been updated';
$content = 'Dear Guest,<br />Your booking has been updated.<br /><br />'; $content = 'Dear Guest,<br />Your booking has been updated.<br /><br />';
$content .= '<table>'; $content .= '<table>';
$content .= '<tr><td>Name: </td><td>'.$booking->guest_name.'</td></tr>';
$content .= '<tr><td>Email: </td><td>'.$booking->guest_email.'</td></tr>';
$content .= '<tr><td>Phone: </td><td>'.$booking->guest_phone.'</td></tr>';
$content .= '<tr><td>Worker: </td><td>'.$worker->worker_name.'</td></tr>'; $content .= '<tr><td>Worker: </td><td>'.$worker->worker_name.'</td></tr>';
$content .= '<tr><td>Date: </td><td>'.$newBookingDate.'</td></tr>'; $content .= '<tr><td>Date: </td><td>'.$newBookingDate.'</td></tr>';
$content .= '<tr><td>Time: </td><td>'.$newStartTime.' - '.$finishTime.'</td></tr>'; $content .= '<tr><td>Time: </td><td>'.$newStartTime.' - '.$finishTime.'</td></tr>';
$content .= '<tr><td>Services: </td><td><table>'; $content .= '<tr><td>Services: </td><td><table>';
foreach($serviceArray as $s){ $content .= '<tr><td>'.$s->service_name_en.'</td><td>'.$s->service_price.' kr</td></tr>'; } foreach($serviceArray as $s){ $content .= '<tr><td>'.$s->service_name_en.'</td><td>'.$s->service_price.' kr</td></tr>'; }
$content .= '</table></td><tr><td>Total price: </td><td><strong>'.$totalServicePrice.' kr</strong></td></tr></table>'; $content .= '</table></td>';
$content .= '<br /><br /><a href="'.$manageLink.'">Manage booking</a>'; $content .= '<tr><td>Total price: </td><td><strong>'.$totalServicePrice.' kr</strong></td></tr>';
$content .= '<br /><br /> STUDIOBEVE'; $content .= '</table>';
$content .= '<br /><br /><a href="'.$manageLink.'">Manage booking</a><br />';
$content .= '<br /> If something comes up and you cant make it to your booked appointment, please let us know at least 24 hours in advance so we can offer the time slot to another guest and our colleagues time wont remain unused; cancellations within 24 hours or no-shows will be charged the full service fee; you can cancel by emailing <a href="mailto:info@studiobeve.no">info@studiobeve.no</a>, or by sending us a message on Instagram or Facebook. Thank you for your understanding and cooperation!';
$content .= '<br />';
$content .= '<br /> STUDIOBEVE';
} }
$emailArray = array(array( $emailArray = array(array(
+28 -11
View File
@@ -396,7 +396,7 @@ class Service_model extends CI_Model {
} }
public function getAvailableTimes($worker_id, $selectedDate, $servicelength) { public function getAvailableTimes($worker_id, $selectedDate, $servicelength, $exclude_booking_id = null) {
$this->load->database(); $this->load->database();
// múltbeli napra ne lehessen foglalni // múltbeli napra ne lehessen foglalni
@@ -490,10 +490,17 @@ class Service_model extends CI_Model {
$allBookings = []; $allBookings = [];
if ($lunchRequired) { if ($lunchRequired) {
$allBookings = $this->db->query(" if ($exclude_booking_id !== null) {
SELECT booking_start_time, booking_finish_time FROM bookings $allBookings = $this->db->query("
WHERE booking_date = ? AND worker_id = ? SELECT booking_start_time, booking_finish_time FROM bookings
", array($selectedDate, $worker_id))->result(); WHERE booking_date = ? AND worker_id = ? AND booking_id != ?
", array($selectedDate, $worker_id, $exclude_booking_id))->result();
} else {
$allBookings = $this->db->query("
SELECT booking_start_time, booking_finish_time FROM bookings
WHERE booking_date = ? AND worker_id = ?
", array($selectedDate, $worker_id))->result();
}
} }
$interval = new DateInterval('PT15M'); $interval = new DateInterval('PT15M');
@@ -508,12 +515,22 @@ class Service_model extends CI_Model {
$startTimeStr = $current->format('H:i:s'); $startTimeStr = $current->format('H:i:s');
$endTimeStr = $slotEnd->format('H:i:s'); $endTimeStr = $slotEnd->format('H:i:s');
$bookingQuery = $this->db->query(" if ($exclude_booking_id !== null) {
SELECT * FROM bookings $bookingQuery = $this->db->query("
WHERE booking_date = ? SELECT * FROM bookings
AND worker_id = ? WHERE booking_date = ?
AND booking_start_time < ? AND booking_finish_time > ? AND worker_id = ?
", array($selectedDate, $worker_id, $endTimeStr, $startTimeStr)); AND booking_id != ?
AND booking_start_time < ? AND booking_finish_time > ?
", array($selectedDate, $worker_id, $exclude_booking_id, $endTimeStr, $startTimeStr));
} else {
$bookingQuery = $this->db->query("
SELECT * FROM bookings
WHERE booking_date = ?
AND worker_id = ?
AND booking_start_time < ? AND booking_finish_time > ?
", array($selectedDate, $worker_id, $endTimeStr, $startTimeStr));
}
if ($bookingQuery->num_rows() > 0) continue; // already booked if ($bookingQuery->num_rows() > 0) continue; // already booked
+2 -1
View File
@@ -562,7 +562,8 @@
action: 'getAvailableTimes', action: 'getAvailableTimes',
worker_id: $('#worker_id').val(), worker_id: $('#worker_id').val(),
servicelength: $('#servicelength').val(), servicelength: $('#servicelength').val(),
selectedDate: selectedDate selectedDate: selectedDate,
manage_token: '<?php echo $token; ?>'
}, },
}).done(function(result){ }).done(function(result){
if(result != 0){ if(result != 0){