PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.7
VikBooking Hotel Booking Engine & PMS v1.8.7
1.8.16 1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 All 37 releases
vikbooking / site / views / booking / view.html.php

view.html.php in VikBooking Hotel Booking Engine & PMS 1.8.7, at site/views/booking/view.html.php

432 lines 15.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package VikBooking
4 * @subpackage com_vikbooking
5 * @author Alessio Gaggii - e4j - Extensionsforjoomla.com
6 * @copyright Copyright (C) 2018 e4j - Extensionsforjoomla.com. All rights reserved.
7 * @license GNU General Public License version 2 or later; see LICENSE
8 * @link https://vikwp.com
9 */
10
11 defined('ABSPATH') or die('No script kiddies please!');
12
13 jimport('joomla.application.component.view');
14
15 class VikbookingViewBooking extends JViewVikBooking
16 {
17 public function display($tpl = null)
18 {
19 $dbo = JFactory::getDbo();
20 $app = JFactory::getApplication();
21 $document = JFactory::getDocument();
22 $vbo_tn = VikBooking::getTranslator();
23
24 // validation of data and availability before the rendering
25 $sid = VikRequest::getString('sid', '', 'request');
26 $ts = VikRequest::getString('ts', '', 'request');
27 if (empty($sid) || empty($ts)) {
28 showSelectVb(JText::translate('VBINSUFDATA'));
29 return;
30 }
31
32 $q = "SELECT `o`.*,(SELECT SUM(`or`.`adults`) FROM `#__vikbooking_ordersrooms` AS `or` WHERE `or`.`idorder`=`o`.`id`) AS `tot_adults` FROM `#__vikbooking_orders` AS `o` WHERE (`o`.`sid`=" . $dbo->quote($sid) . " OR `o`.`idorderota`=" . $dbo->quote($sid) . ") AND `o`.`ts`=" . $dbo->quote($ts);
33 $dbo->setQuery($q, 0, 1);
34 $order = $dbo->loadAssoc();
35 if (!$order) {
36 showSelectVb(JText::translate('VBORDERNOTFOUND'));
37 return;
38 }
39
40 // availability helper
41 $av_helper = VikBooking::getAvailabilityInstance();
42
43 // room stay dates in case of split stay
44 $room_stay_dates = [];
45 if ($order['split_stay']) {
46 if ($order['status'] == 'confirmed') {
47 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($order['id']);
48 } else {
49 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $order['id'], []);
50 }
51 }
52
53 if ($order['status'] == 'confirmed') {
54 // prepare impression data for channels
55 $impressiondata = $order;
56 $q = "SELECT `or`.`idtar`,`d`.`idprice`,`p`.`idiva`,`t`.`aliq`,`t`.`taxcap` FROM `#__vikbooking_ordersrooms` AS `or` " .
57 "LEFT JOIN `#__vikbooking_dispcost` `d` ON `d`.`id`=`or`.`idtar` " .
58 "LEFT JOIN `#__vikbooking_prices` `p` ON `p`.`id`=`d`.`idprice` " .
59 "LEFT JOIN `#__vikbooking_iva` `t` ON `t`.`id`=`p`.`idiva` " .
60 "WHERE `or`.`idorder`='".$order['id']."' ORDER BY `t`.`aliq` ASC";
61 $dbo->setQuery($q, 0, 1);
62 $taxdata = $dbo->loadAssoc();
63 if ($taxdata) {
64 $taxes = 0;
65 if (!empty($taxdata['aliq'])) {
66 $realtotal = round(($order['total'] / ((100 + $taxdata['aliq']) / 100)), 2);
67 $taxes = round(($order['total'] - $realtotal), 2);
68 /**
69 * Tax Cap implementation.
70 *
71 * @since 1.12
72 */
73 if ($taxdata['taxcap'] > 0 && $taxes > $taxdata['taxcap']) {
74 $realtotal = $order['total'] - $taxdata['taxcap'];
75 $taxes = $taxdata['taxcap'];
76 }
77 $impressiondata['total'] = $realtotal;
78 }
79 $impressiondata['taxes'] = $taxes;
80 $impressiondata['fees'] = 0;
81 }
82 VikBooking::invokeChannelManager(true, $impressiondata);
83 // end prepare impression data for channels
84 } elseif ($order['status'] == 'standby') {
85 $roomavail = false;
86
87 $q = $dbo->getQuery(true)
88 ->select($dbo->qn('or') . '.*')
89 ->select($dbo->qn('r.units'))
90 ->from($dbo->qn('#__vikbooking_ordersrooms', 'or'))
91 ->leftJoin($dbo->qn('#__vikbooking_rooms', 'r') . ' ON ' . $dbo->qn('or.idroom') . ' = ' . $dbo->qn('r.id'))
92 ->where($dbo->qn('or.idorder') . ' = ' . (int)$order['id'])
93 ->order($dbo->qn('or.id') . ' ASC');
94
95 $dbo->setQuery($q);
96 $orderrooms = $dbo->loadAssocList();
97
98 /**
99 * Even if redundant, we read the eventually occupied records by this booking ID to ensure
100 * server-side cache will not produce a booking cancellation after receiving a valid payment.
101 * An eventual list of busy record IDs is passed to the method for checking if the room is
102 * available, because the status of the reservation may actually be confirmed already.
103 *
104 * @since 1.16.9 (J) - 1.6.9 (WP)
105 */
106 $dbo->setQuery(
107 $dbo->getQuery(true)
108 ->select($dbo->qn('idbusy'))
109 ->from($dbo->qn('#__vikbooking_ordersbusy'))
110 ->where($dbo->qn('idorder') . ' = ' . (int)$order['id'])
111 );
112 $skip_busy_ids = array_column($dbo->loadAssocList(), 'idbusy');
113
114 foreach ($orderrooms as $kor => $or) {
115 // determine proper values for this room
116 $room_stay_checkin = $order['checkin'];
117 $room_stay_checkout = $order['checkout'];
118 if ($order['split_stay'] && $room_stay_dates && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
119 $room_stay_checkin = !empty($room_stay_dates[$kor]['checkin_ts']) ? $room_stay_dates[$kor]['checkin_ts'] : $room_stay_dates[$kor]['checkin'];
120 $room_stay_checkout = !empty($room_stay_dates[$kor]['checkout_ts']) ? $room_stay_dates[$kor]['checkout_ts'] : $room_stay_dates[$kor]['checkout'];
121 }
122
123 // make sure room is still available
124 $roomavail = VikBooking::roomBookable($or['idroom'], $or['units'], $room_stay_checkin, $room_stay_checkout, $skip_busy_ids);
125 if (!$roomavail) {
126 break;
127 }
128 }
129
130 $today_midnight = mktime(0, 0, 0, date('n'), date('j'), date('Y'));
131 $autoremove = false;
132 if ($today_midnight > $order['checkin']) {
133 $roomavail = false;
134 }
135 $minautoremove = VikBooking::getMinutesAutoRemove();
136 $mins_elapsed = floor((time() - $order['ts']) / 60);
137 if ($minautoremove > 0 && $mins_elapsed > $minautoremove) {
138 $roomavail = false;
139 $autoremove = true;
140 }
141
142 /**
143 * Make sure not to cancel an OTA pending reservation.
144 *
145 * @since 1.15.4 (J) - 1.5.10 (WP)
146 */
147 $is_ota_pending = (!empty($order['type']) && !empty($order['channel']));
148
149 if ($roomavail || $is_ota_pending) {
150 // invoke channel impression
151 VikBooking::invokeChannelManager(false);
152 //
153 } else {
154 // set the booking to cancelled
155 $q = "UPDATE `#__vikbooking_orders` SET `status`='cancelled' WHERE `id`=".(int)$order['id'].";";
156 $dbo->setQuery($q);
157 $dbo->execute();
158 // update status in the array
159 $order['status'] = 'cancelled';
160 //
161 $q = "DELETE FROM `#__vikbooking_tmplock` WHERE `idorder`=" . (int)$order['id'] . ";";
162 $dbo->setQuery($q);
163 $dbo->execute();
164 $q = "SELECT * FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$order['id'].";";
165 $dbo->setQuery($q);
166 $ordbusy = $dbo->loadAssocList();
167 if ($ordbusy) {
168 foreach ($ordbusy as $ob) {
169 $q = "DELETE FROM `#__vikbooking_busy` WHERE `id`=".(int)$ob['idbusy'].";";
170 $dbo->setQuery($q);
171 $dbo->execute();
172 }
173 }
174 $q = "DELETE FROM `#__vikbooking_ordersbusy` WHERE `idorder`=".(int)$order['id'].";";
175 $dbo->setQuery($q);
176 $dbo->execute();
177
178 /**
179 * We now save onto a var the full error message to understand what made the booking become cancelled.
180 * This way, by checking the booking history it will be easy to understand the cause of the issue.
181 *
182 * @since October 15th 2020
183 */
184 $history_err_descr = '';
185 if ($today_midnight > $order['checkin']) {
186 $history_err_descr = JText::translate('VBOBOOKNOLONGERPAYABLE');
187 } elseif ($autoremove === true) {
188 $history_err_descr = JText::translate('VBOERRAUTOREMOVED');
189 } else {
190 $history_err_descr = JText::translate('VBERRREPSEARCH');
191 }
192 if (!empty($history_err_descr)) {
193 VikError::raiseWarning('', $history_err_descr);
194 }
195
196 //Booking History
197 VikBooking::getBookingHistoryInstance()->setBid($order['id'])->store('CA', $history_err_descr);
198 //
199 }
200 }
201
202 // render the booking details
203
204 // set noindex instruction for robots
205 $document->setMetaData('robots', 'noindex, nofollow');
206
207 // load jQuery
208 if (VikBooking::loadJquery()) {
209 JHtml::fetch('jquery.framework', true, true);
210 }
211
212 $tars = [];
213 $cookie = $app->input->cookie;
214 $pcheckin = $order['checkin'];
215 $pcheckout = $order['checkout'];
216 $secdiff = $pcheckout - $pcheckin;
217 $daysdiff = $secdiff / 86400;
218 if (is_int($daysdiff)) {
219 if ($daysdiff < 1) {
220 $daysdiff = 1;
221 }
222 } else {
223 if ($daysdiff < 1) {
224 $daysdiff = 1;
225 } else {
226 $sum = floor($daysdiff) * 86400;
227 $newdiff = $secdiff - $sum;
228 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
229 if ($maxhmore >= $newdiff) {
230 $daysdiff = floor($daysdiff);
231 } else {
232 $daysdiff = ceil($daysdiff);
233 }
234 }
235 }
236 $is_package = !empty($order['pkg']) ? true : false;
237
238 // get the rooms booked list
239 $dbo->setQuery(
240 $dbo->getQuery(true)
241 ->select($dbo->qn('or') . '.*')
242 ->select($dbo->qn('r.id', 'r_reference_id'))
243 ->select([
244 $dbo->qn('r.name'),
245 $dbo->qn('r.img'),
246 $dbo->qn('r.idcarat'),
247 $dbo->qn('r.fromadult'),
248 $dbo->qn('r.toadult'),
249 ])
250 ->from($dbo->qn('#__vikbooking_ordersrooms', 'or'))
251 ->leftJoin($dbo->qn('#__vikbooking_rooms', 'r') . ' ON ' . $dbo->qn('or.idroom') . ' = ' . $dbo->qn('r.id'))
252 ->where($dbo->qn('or.idorder') . ' = ' . (int)$order['id'])
253 ->order($dbo->qn('or.id') . ' ASC')
254 );
255 $orderrooms = $dbo->loadAssocList();
256
257 if ($orderrooms) {
258 $vbo_tn->translateContents($orderrooms, '#__vikbooking_rooms', array('id' => 'r_reference_id'));
259 foreach ($orderrooms as $kor => $or) {
260 $num = $kor + 1;
261 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
262 //package or custom cost set from the back-end
263 continue;
264 }
265 $q = "SELECT `t`.*,`p`.`name`,`p`.`free_cancellation`,`p`.`canc_deadline`,`p`.`canc_policy` FROM `#__vikbooking_dispcost` AS `t` LEFT JOIN `#__vikbooking_prices` AS `p` ON `t`.`idprice`=`p`.`id` WHERE `t`.`id`=" . (int)$or['idtar'] . ";";
266 $dbo->setQuery($q);
267 $tar = $dbo->loadAssocList();
268 if (!$tar) {
269 continue;
270 }
271 $vbo_tn->translateContents($tar, '#__vikbooking_prices', array('id' => 'idprice'));
272
273 // determine proper values for this room
274 $room_stay_checkin = $order['checkin'];
275 $room_stay_checkout = $order['checkout'];
276 $room_stay_nights = $order['days'];
277 if ($order['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$kor]) && $room_stay_dates[$kor]['idroom'] == $or['idroom']) {
278 $room_stay_checkin = !empty($room_stay_dates[$kor]['checkin_ts']) ? $room_stay_dates[$kor]['checkin_ts'] : $room_stay_dates[$kor]['checkin'];
279 $room_stay_checkout = !empty($room_stay_dates[$kor]['checkout_ts']) ? $room_stay_dates[$kor]['checkout_ts'] : $room_stay_dates[$kor]['checkout'];
280 $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout);
281 }
282
283 // apply seasonal rates
284 $tar = VikBooking::applySeasonsRoom($tar, $room_stay_checkin, $room_stay_checkout);
285
286 // apply OBP rules
287 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
288
289 // push tariffs
290 $tars[$num] = $tar[0];
291 }
292 }
293
294 $days_to_arrival = 0;
295 $now_info = getdate();
296 $checkin_info = getdate($order['checkin']);
297 if ($now_info[0] < $checkin_info[0]) {
298 while ($now_info[0] < $checkin_info[0]) {
299 if (!($now_info['mday'] != $checkin_info['mday'] || $now_info['mon'] != $checkin_info['mon'] || $now_info['year'] != $checkin_info['year'])) {
300 break;
301 }
302 $days_to_arrival++;
303 $now_info = getdate(mktime(0, 0, 0, $now_info['mon'], ($now_info['mday'] + 1), $now_info['year']));
304 }
305 }
306
307 $is_refundable = 0;
308 $daysadv_refund_arr = [];
309 $daysadv_refund = 0;
310 $canc_policy = '';
311 foreach ($tars as $num => $tar) {
312 if ($tar['free_cancellation'] < 1) {
313 // if at least one rate plan is non-refundable, the whole reservation cannot be cancelled
314 $is_refundable = 0;
315 $daysadv_refund_arr = [];
316 break;
317 }
318 $is_refundable = 1;
319 $daysadv_refund_arr[] = $tar['canc_deadline'];
320 }
321
322 // get the rate plan with the lowest cancellation deadline
323 $daysadv_refund = count($daysadv_refund_arr) > 0 ? min($daysadv_refund_arr) : $daysadv_refund;
324 if ($daysadv_refund > 0) {
325 foreach ($tars as $num => $tar) {
326 if ($tar['free_cancellation'] > 0 && $tar['canc_deadline'] == $daysadv_refund) {
327 //get the cancellation policy from the first rate plan with free cancellation and same cancellation deadline
328 $canc_policy = $tar['canc_policy'];
329 break;
330 }
331 }
332 }
333
334 $payment = "";
335 if (!empty($order['idpayment'])) {
336 $exppay = explode('=', $order['idpayment']);
337 $payment = VikBooking::getPayment($exppay[0], $vbo_tn);
338 }
339 $pnodep = VikRequest::getString('nodep', '', 'request');
340 $cnodep = $cookie->get('vboFA', '', 'string');
341 $nodep = intval($pnodep) > 0 || intval($cnodep) > 0 ? 1 : 0;
342
343 /**
344 * Scan the booking and related rooms for damage deposit payment data.
345 * Obtain also the information about possible previous payments.
346 *
347 * @since 1.17.6 (J) - 1.7.6 (WP)
348 */
349 $damage_deposit_payment = VBORoomHelper::getInstance()->getDamageDepositSplitPayment($order, $orderrooms);
350 $prev_dd_payments = [];
351 if ($damage_deposit_payment['damagedep_gross'] ?? 0) {
352 $prev_dd_payments = VikBooking::getBookingHistoryInstance($order['id'])
353 ->getEventsWithData('PN', function($data) {
354 return (is_object($data) && !empty($data->damage_deposit));
355 });
356 if (!$prev_dd_payments) {
357 // check also the first payment event in case of OTA bookings
358 $prev_dd_payments = VikBooking::getBookingHistoryInstance($order['id'])
359 ->getEventsWithData('P0', function($data) {
360 return (is_object($data) && !empty($data->damage_deposit));
361 });
362 }
363 }
364
365 /**
366 * Upselling extra services only for non-cancelled bookings
367 * with a check-out date in the future.
368 *
369 * @since 1.13.0 (J) - 1.3.0 (WP)
370 */
371 $upselling = [];
372 if ($order['status'] != 'cancelled' && VikBooking::upsellingEnabled() && $order['checkout'] > time()) {
373 $upsell_data = [];
374 foreach ($orderrooms as $kor => $or) {
375 $room_data = new stdClass;
376 $room_data->id = $or['idroom'];
377 $room_data->name = $or['name'];
378 $room_data->img = $or['img'];
379 $room_data->adults = $or['adults'];
380 $room_data->children = $or['children'];
381 $room_data->nights = $order['days'];
382 $room_data->options = [];
383 if (!empty($or['optionals'])) {
384 $optids = explode(';', $or['optionals']);
385 foreach ($optids as $optid) {
386 if (!empty($optid)) {
387 // the : may express the quantity
388 $optidparts = explode(':', $optid);
389 array_push($room_data->options, (int)$optidparts[0]);
390 }
391 }
392 }
393 array_push($upsell_data, $room_data);
394 }
395 $upselling = VikBooking::loadUpsellingData($upsell_data, $order, $vbo_tn);
396 }
397
398 /**
399 * Trigger first tracking conversion on booking.
400 *
401 * @since 1.16.3 (J) - 1.6.3 (WP)
402 */
403 VikBooking::getTracker()->triggerBookingConversion($order);
404
405 $this->ord = $order;
406 $this->orderrooms = $orderrooms;
407 $this->tars = $tars;
408 $this->days_to_arrival = $days_to_arrival;
409 $this->is_refundable = $is_refundable;
410 $this->daysadv_refund = $daysadv_refund;
411 $this->canc_policy = $canc_policy;
412 $this->payment = $payment;
413 $this->nodep = $nodep;
414 $this->upselling = $upselling;
415 $this->damage_deposit_payment = $damage_deposit_payment;
416 $this->prev_dd_payments = $prev_dd_payments;
417 $this->vbo_tn = $vbo_tn;
418
419 // theme
420 $theme = VikBooking::getTheme();
421 if ($theme != 'default') {
422 $thdir = VBO_SITE_PATH . DIRECTORY_SEPARATOR . 'themes' . DIRECTORY_SEPARATOR . $theme . DIRECTORY_SEPARATOR . 'booking';
423 if (is_dir($thdir)) {
424 $this->_setPath('template', $thdir . DIRECTORY_SEPARATOR);
425 }
426 }
427 //
428
429 parent::display($tpl);
430 }
431 }
432