PluginProbe
VikBooking Hotel Booking Engine & PMS / 1.8.6
VikBooking Hotel Booking Engine & PMS v1.8.6
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 / admin / views / editorder / tmpl / default.php

default.php in VikBooking Hotel Booking Engine & PMS 1.8.6, at admin/views/editorder/tmpl/default.php

4,337 lines 183.9 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 $row = $this->row;
14 $rooms = $this->rooms;
15 $busy = $this->busy;
16 $customer = $this->customer;
17 $payments = $this->payments;
18
19 $history_obj = VikBooking::getBookingHistoryInstance($row['id']);
20
21 // availability helper
22 $av_helper = VikBooking::getAvailabilityInstance();
23
24 // load datepicker for all CMS compatibility
25 JHtml::fetch('stylesheet', VBO_SITE_URI.'resources/jquery-ui.min.css');
26 JHtml::fetch('jquery.framework', true, true);
27 JHtml::fetch('script', VBO_SITE_URI.'resources/jquery-ui.min.js');
28
29 // js lang def
30 JText::script('VBO_CONV_RES_OTA_CURRENCY_APPLY');
31 JText::script('VBDELCONFIRM');
32 JText::script('VBSENDCANCORDEMAIL');
33 JText::script('VBO_SET_STANDBY');
34 JText::script('VBO_CONF_RM_OVERBOOKING_FLAG');
35 JText::script('VBO_NEW_PAYSCHEDULE');
36 JText::script('VBANNULLA');
37 JText::script('VBOCLOSE');
38 JText::script('VBSAVE');
39 JText::script('VBELIMINA');
40 JText::script('VBO_REG_NEW_PAYMENT');
41 JText::script('VBO_UPDATE_PAYMENT');
42 JText::script('VBSENDSMSACTION');
43 JText::script('VBSENDEMAILACTION');
44 JText::script('VBO_AI_AUTO_GUEST_REV_EXCLUDE');
45 JText::script('VBO_AI_AUTO_GUEST_REV_INCLUDE');
46
47 $dbo = JFactory::getDbo();
48
49 $vbo_app = VikBooking::getVboApplication();
50 $vbo_app->loadVisualEditorAssets();
51 $vbo_app->prepareJavaScriptCurrency();
52
53 // preload chat assets
54 VBOFactory::getChatMediator()->useAssets();
55
56 /**
57 * This View can render within a modal the "bookingcheckin" View, and with WP
58 * this is loaded via AJAX. In order to not interfere or reset the contextual menu,
59 * we load the assets from the parent View. Context menu may also be used in this View.
60 *
61 * @since 1.16.0 (J) - 1.6.0 (WP)
62 */
63 $vbo_app->loadContextMenuAssets();
64 if (VBOPlatformDetection::isWordPress()) {
65 JText::script('VBRENTALORD');
66 JText::script('VBPVIEWORDERSPEOPLE');
67 }
68
69 $canDo = JFactory::getUser();
70 $vbo_auth_bookings = $canDo->authorise('core.vbo.bookings', 'com_vikbooking');
71
72 // check if automatic payment collection is enabled for all bookings
73 $automatic_payment_collection = VBOFactory::getConfig()->getBool('auto_payment_collection', false);
74
75 $booking_has_damage_dep = 0;
76 $current_ts = time();
77 $ota_type_data = !empty($row['ota_type_data']) ? ((array) json_decode($row['ota_type_data'], true)) : [];
78 $currencyname = VikBooking::getCurrencyName();
79 $currencysymb = VikBooking::getCurrencySymb();
80 $after_tax = VikBooking::ivaInclusa();
81 $nowdf = VikBooking::getDateFormat(true);
82 if ($nowdf == "%d/%m/%Y") {
83 $df = 'd/m/Y';
84 } elseif ($nowdf == "%m/%d/%Y") {
85 $df = 'm/d/Y';
86 } else {
87 $df = 'Y/m/d';
88 }
89 $datesep = VikBooking::getDateSeparator(true);
90 $vbo_modals_html = array();
91 $payment = VikBooking::getPayment($row['idpayment']);
92 $pactive_tab = VikRequest::getString('vbo_active_tab', 'vbo-tab-details', 'request');
93 $printreceipt = VikRequest::getInt('print', 0, 'request');
94 $printreceipt = ($printreceipt > 0);
95 if ($printreceipt) {
96 //we set a different page title when printing the receipt for the "PDF Printer" to give the file a good name.
97 JFactory::getDocument()->setTitle(VikBooking::getFrontTitle()." - ".JText::translate('VBOFISCRECEIPT')." #".$row['id']);
98 }
99 $gotouri = 'index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id'];
100
101 if ($row['status'] == "confirmed") {
102 $use_js_bid = $row['id'];
103 JFactory::getDocument()->addScriptDeclaration(
104 <<<JS
105 window["vbo_current_bid"] = $use_js_bid;
106 JS
107 );
108 }
109
110 $tars = array();
111 $arrpeople = array();
112 $is_package = !empty($row['pkg']) ? true : false;
113 $is_cust_cost = false;
114 foreach ($rooms as $ind => $or) {
115 $num = $ind + 1;
116 $arrpeople[$num]['adults'] = $or['adults'];
117 $arrpeople[$num]['children'] = $or['children'];
118 $arrpeople[$num]['children_age'] = $or['childrenage'];
119 $arrpeople[$num]['t_first_name'] = $or['t_first_name'];
120 $arrpeople[$num]['t_last_name'] = $or['t_last_name'];
121 $arrpeople[$num]['pets'] = $or['pets'];
122 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
123 //package or custom cost set from the back-end
124 $is_cust_cost = true;
125 continue;
126 }
127 $q = "SELECT * FROM `#__vikbooking_dispcost` WHERE `id`=".(int)$or['idtar'].";";
128 $dbo->setQuery($q);
129 $tar = $dbo->loadAssocList();
130 $tar = VikBooking::applySeasonsRoom($tar, $row['checkin'], $row['checkout']);
131
132 // apply OBP rules
133 $tar = VBORoomHelper::getInstance()->applyOBPRules($tar, $or, $or['adults']);
134
135 $tars[$num] = $tar;
136 }
137 $pcheckin = $row['checkin'];
138 $pcheckout = $row['checkout'];
139 $secdiff = $pcheckout - $pcheckin;
140 $daysdiff = $secdiff / 86400;
141 if (is_int($daysdiff)) {
142 if ($daysdiff < 1) {
143 $daysdiff = 1;
144 }
145 } else {
146 if ($daysdiff < 1) {
147 $daysdiff = 1;
148 } else {
149 $sum = floor($daysdiff) * 86400;
150 $newdiff = $secdiff - $sum;
151 $maxhmore = VikBooking::getHoursMoreRb() * 3600;
152 if ($maxhmore >= $newdiff) {
153 $daysdiff = floor($daysdiff);
154 } else {
155 $daysdiff = ceil($daysdiff);
156 }
157 }
158 }
159
160 $otachannel = '';
161 $otachannel_name = '';
162 $otachannel_bid = '';
163 $otacurrency = '';
164 if (!empty($row['channel'])) {
165 $channelparts = explode('_', $row['channel']);
166 $otachannel = array_key_exists(1, $channelparts) && strlen($channelparts[1]) > 0 ? $channelparts[1] : ucwords($channelparts[0]);
167 $otachannel_name = $otachannel;
168 $otachannel_bid = $otachannel.(!empty($row['idorderota']) ? ' - Booking ID: '.$row['idorderota'] : '');
169 if (strstr($otachannel, '.') !== false) {
170 $otaccparts = explode('.', $otachannel);
171 $otachannel = $otaccparts[0];
172 }
173 $otacurrency = strlen((string) $row['chcurrency']) > 0 ? $row['chcurrency'] : '';
174 }
175
176 /**
177 * Tell whether the current reservation has or may have a CC/VCC available.
178 */
179 $may_have_cc_details = false;
180 if (!empty($row['paymentlog']) && stripos($row['paymentlog'], 'card number') !== false && strpos($row['paymentlog'], '****') !== false) {
181 // turn flag on for partial card details available
182 $may_have_cc_details = true;
183 } elseif (!empty($row['channel']) && !strcasecmp($otachannel_name, 'Booking.com')) {
184 // the CM may be able to retrieve the CC details via API
185 $may_have_cc_details = true;
186 }
187
188 $status_type = '';
189 if (!empty($row['type'])) {
190 $status_type = JText::translate('VBO_BTYPE_' . strtoupper($row['type']));
191 if (!strcasecmp($row['type'], 'overbooking')) {
192 $status_type = '<span class="label label-error vbo-label-nested vbo-label-overbooking">' . $status_type . '</span>';
193 }
194 $status_type .= ' / ';
195 }
196 $extra_status = $row['refund'] > 0 ? ' / ' . JText::translate('VBO_STATUS_REFUNDED') : '';
197 if ($row['status'] == "confirmed") {
198 $saystaus = '<span class="label label-success">' . $status_type . JText::translate('VBCONFIRMED') . $extra_status . '</span>';
199 } elseif ($row['status'] == "standby") {
200 $saystaus = '<span class="label label-warning">' . $status_type . JText::translate('VBSTANDBY') . $extra_status . '</span>';
201 } else {
202 $saystaus = '<span class="label label-error">' . $status_type . JText::translate('VBCANCELLED') . $extra_status . '</span>';
203 }
204
205 // extend booking details main panel
206 $bookingPanelForms = $this->onDisplayView();
207
208 // extend booking details sidebar
209 $bookingSidebarForms = $this->onDisplayView('Sidebar');
210
211 // extend administration main panel
212 $adminFormsSetup = new stdClass;
213 $adminFormsSetup->icons = [];
214 $adminPanelForms = $this->onDisplayView('Administration', $adminFormsSetup);
215
216 // extend administration sidebar
217 $adminSidebarForms = $this->onDisplayView('AdministrationSidebar');
218
219 //Prepare modal (used for the Registration and for reconstructing the credit card details through the channel manager)
220 echo $vbo_app->getJmodalScript();
221 //end Prepare modal
222 ?>
223 <script type="text/javascript">
224 function changePayment() {
225 var newpayment = document.getElementById('newpayment').value;
226 if (newpayment != '') {
227 var paymentname = document.getElementById('newpayment').options[document.getElementById('newpayment').selectedIndex].text;
228 if (confirm('<?php echo addslashes(JText::translate('VBCHANGEPAYCONFIRM')); ?>' + paymentname + '?')) {
229 document.adminForm.submit();
230 } else {
231 document.getElementById('newpayment').selectedIndex = 0;
232 }
233 }
234 }
235 function vbToggleLog(elem) {
236 vbToggleDynamicPanel(elem, '#vbpaymentlogdiv');
237 }
238 function vbToggleNotes(elem) {
239 vbToggleDynamicPanel(elem, '#vbadminnotesdiv');
240 }
241 function vbToggleHistory(elem) {
242 vbToggleDynamicPanel(elem, '#vbhistorydiv');
243 }
244 function vbToggleInvNotes(elem) {
245 vbToggleDynamicPanel(elem, '#vbinvnotesdiv');
246 }
247 function vbToggleMessaging(elem) {
248 vbToggleDynamicPanel(elem, '#vbmessagingdiv');
249 if (typeof VCMChat !== 'undefined') {
250 VCMChat.getInstance().scrollToBottom();
251 }
252 }
253 function vbToggleDynamicPanel(elem, target) {
254 if (jQuery(target).is(':visible')) {
255 return;
256 }
257
258 jQuery(".vbo-bookingdet-noteslogs-btn-active").removeClass("vbo-bookingdet-noteslogs-btn-active");
259
260 jQuery('.vbo-extra-panel').hide();
261 jQuery(target).show();
262
263 jQuery(elem).parent(".vbo-bookingdet-noteslogs-btn").addClass("vbo-bookingdet-noteslogs-btn-active");
264
265 if (typeof sessionStorage !== 'undefined') {
266 sessionStorage.setItem('vboEditOrderTab<?php echo $row['id']; ?>', jQuery(elem).parent().data('id'));
267 }
268 }
269 function toggleDiscount(elem) {
270 var discsp = document.getElementById('vbdiscenter').style.display;
271 if (discsp == 'block') {
272 document.getElementById('vbdiscenter').style.display = 'none';
273 jQuery(elem).find('i').attr('class', '<?php echo VikBookingIcons::i('chevron-down'); ?>');
274 } else {
275 document.getElementById('vbdiscenter').style.display = 'block';
276 jQuery(elem).find('i').attr('class', '<?php echo VikBookingIcons::i('chevron-up'); ?>');
277 }
278 }
279 </script>
280
281 <div class="vbo-bookingdet-topcontainer">
282 <form name="adminForm" id="adminForm" action="<?php echo VBOPlatformDetection::isWordPress() ? 'admin.php' : 'index.php'; ?>?option=com_vikbooking&amp;task=editorder&amp;cid[]=<?php echo $row['id']; ?>" method="post">
283 <?php
284 if ($printreceipt) {
285 //print the company details
286 $companylogo = VikBooking::getSiteLogo();
287 $next_receipt = VikBooking::getNextReceiptNumber($row['id']);
288 ?>
289 <div class="vbo-receipt-company-block-outer">
290 <div class="vbo-receipt-company-block">
291 <?php
292 if (!empty($companylogo)) {
293 ?>
294 <div class="vbo-receipt-company-logo"><img src="<?php echo VBO_ADMIN_URI.'resources/'.$companylogo; ?>" /></div>
295 <?php
296 }
297 ?>
298 <div class="vbo-receipt-company-info"><?php echo VikBooking::getInvoiceCompanyInfo(); ?></div>
299 </div>
300 <div class="vbo-receipt-numdate-block">
301 <div class="vbo-receipt-numdate-inner">
302 <div class="vbo-receipt-numdate-title">
303 <span><?php echo JText::translate('VBOFISCRECEIPT'); ?></span>
304 <span style="float: right; cursor: pointer; color: #ff0000;" onclick="vboMakePrintOnly();"><?php VikBookingIcons::e('times-circle'); ?></span>
305 </div>
306 <div class="vbo-receipt-numdate-num">
307 <span class="vbo-receipt-numdate-num-lbl"><?php echo JText::translate('VBOFISCRECEIPTNUM'); ?></span>
308 <span class="vbo-receipt-numdate-num-val">
309 <span class="vbo-showin-print" id="vbo-receipt-num"><?php echo $next_receipt; ?></span>
310 <input class="vbo-hidein-print" id="vbo-receipt-num-inp" type="number" min="0" value="<?php echo $next_receipt; ?>" onchange="document.getElementById('vbo-receipt-num').innerText = this.value;" />
311 </span>
312 </div>
313 <div class="vbo-receipt-numdate-date">
314 <span class="vbo-receipt-numdate-date-lbl"><?php echo JText::translate('VBOFISCRECEIPTDATE'); ?></span>
315 <span class="vbo-receipt-numdate-date-val"><?php echo date(str_replace("/", $datesep, $df)); ?></span>
316 </div>
317 </div>
318 </div>
319 <div class="vbo-receipt-print-confirm vbo-hidein-print">
320 <div class="vbo-receipt-print-btn">
321 <span onclick="vboLaunchPrintReceipt();">
322 <?php VikBookingIcons::e('print'); ?>
323 <span id="vbo-receipt-print-btn-name"><?php echo JText::translate('VBOPRINTRECEIPT'); ?></span>
324 </span>
325 </div>
326 </div>
327 </div>
328 <?php
329 }
330 ?>
331
332 <div class="vbo-bookdet-container">
333 <div class="vbo-bookdet-wrap">
334 <div class="vbo-bookdet-head">
335 <span>ID</span>
336 </div>
337 <div class="vbo-bookdet-foot">
338 <span><?php echo $row['id']; ?></span>
339 </div>
340 </div>
341 <div class="vbo-bookdet-wrap">
342 <div class="vbo-bookdet-head">
343 <span><?php echo JText::translate('VBEDITORDERONE'); ?></span>
344 </div>
345 <div class="vbo-bookdet-foot">
346 <span><?php echo date(str_replace("/", $datesep, $df).' H:i', $row['ts']); ?></span>
347 </div>
348 </div>
349 <?php
350 if (!$printreceipt && $customer) {
351 ?>
352 <div class="vbo-bookdet-wrap">
353 <div class="vbo-bookdet-head">
354 <span><?php echo JText::translate('VBCUSTOMERNOMINATIVE'); ?></span>
355 </div>
356 <div class="vbo-bookdet-foot">
357 <div class="vbo-customer-info-box">
358 <div class="vbo-customer-info-box-name">
359 <?php echo (isset($customer['country_img']) ? $customer['country_img'] . ' ' : ''); ?>
360
361 <?php if ($canDo->authorise('core.edit', 'com_vikbooking') && $canDo->authorise('core.vbo.management', 'com_vikbooking')): ?>
362 <a href="index.php?option=com_vikbooking&task=editcustomer&cid[]=<?php echo $customer['id']; ?>&goto=<?php echo base64_encode($gotouri); ?>"><?php echo ltrim($customer['first_name'] . ' ' . $customer['last_name']); ?></a>
363 <?php else: ?>
364 <?php echo ltrim($customer['first_name'] . ' ' . $customer['last_name']); ?>
365 <?php endif; ?>
366 </div>
367 <?php
368 if (!empty($customer['pic'])) {
369 $avatar_caption = ltrim($customer['first_name'] . ' ' . $customer['last_name']);
370 ?>
371 <div class="vbo-customer-info-box-avatar vbo-customer-avatar-small">
372 <span>
373 <img src="<?php echo strpos($customer['pic'], 'http') === 0 ? $customer['pic'] : VBO_SITE_URI . 'resources/uploads/' . $customer['pic']; ?>" data-caption="<?php echo htmlspecialchars($avatar_caption); ?>" />
374 </span>
375 </div>
376 <?php
377 }
378 ?>
379 </div>
380 </div>
381 </div>
382 <?php
383 }
384 if (!$printreceipt) {
385 ?>
386 <div class="vbo-bookdet-wrap">
387 <div class="vbo-bookdet-head">
388 <span><?php echo JText::translate('VBEDITORDERROOMSNUM'); ?></span>
389 </div>
390 <div class="vbo-bookdet-foot">
391 <?php echo $row['roomsnum']; ?>
392 </div>
393 </div>
394 <?php
395 }
396 ?>
397 <div class="vbo-bookdet-wrap">
398 <div class="vbo-bookdet-head">
399 <span><?php echo JText::translate('VBEDITORDERFOUR'); ?></span>
400 </div>
401 <div class="vbo-bookdet-foot">
402 <span><?php echo $row['days']; ?></span>
403 <?php
404 if ($row['split_stay']) {
405 ?>
406 <span class="hasTooltip" title="<?php echo JHtml::fetch('esc_attr', JText::translate('VBO_SPLIT_STAY')); ?>"><?php VikBookingIcons::e('random'); ?></span>
407 <?php
408 }
409 ?>
410 </div>
411 </div>
412 <div class="vbo-bookdet-wrap">
413 <div class="vbo-bookdet-head">
414 <span><?php echo JText::translate('VBEDITORDERFIVE'); ?></span>
415 </div>
416 <div class="vbo-bookdet-foot">
417 <?php
418 $checkin_info = getdate($row['checkin']);
419 $short_wday = JText::translate('VB'.strtoupper(substr($checkin_info['weekday'], 0, 3)));
420 ?>
421 <?php echo $short_wday.', '.date(str_replace("/", $datesep, $df).' H:i', $row['checkin']); ?>
422 </div>
423 </div>
424 <div class="vbo-bookdet-wrap">
425 <div class="vbo-bookdet-head">
426 <span><?php echo JText::translate('VBEDITORDERSIX'); ?></span>
427 </div>
428 <div class="vbo-bookdet-foot">
429 <?php
430 $checkout_info = getdate($row['checkout']);
431 $short_wday = JText::translate('VB'.strtoupper(substr($checkout_info['weekday'], 0, 3)));
432 ?>
433 <?php echo $short_wday.', '.date(str_replace("/", $datesep, $df).' H:i', $row['checkout']); ?>
434 </div>
435 </div>
436 <?php
437 if (!$printreceipt && $vbo_auth_bookings && $row['closure'] != 1 && $row['status'] == 'confirmed') {
438 // we don't need to check in the IF above "&& $row['checked'] != 0" because the registration is useful for all bookings.
439 $checked_btn = 'btn-primary';
440 switch ($row['checked']) {
441 case -1:
442 $checked_status = JText::translate('VBOCHECKEDSTATUSNOS');
443 $checked_btn = 'btn-danger';
444 break;
445 case 1:
446 $checked_status = JText::translate('VBOCHECKEDSTATUSIN');
447 $checked_btn = 'btn-success';
448 break;
449 case 2:
450 $checked_status = JText::translate('VBOCHECKEDSTATUSOUT');
451 $checked_btn = 'btn-warning';
452 break;
453 default:
454 $checked_status = JText::translate('VBOCHECKEDSTATUSZERO');
455 if ($customer && isset($customer['pax_data']) && !empty($customer['pax_data'])) {
456 // pre check-in performed via front-end
457 $checked_status = JText::translate('VBOCHECKEDSTATUSPRECHECKIN');
458 }
459 break;
460 }
461 ?>
462 <div class="vbo-bookdet-wrap pro-feature">
463 <div class="vbo-bookdet-head">
464 <span><?php echo JText::translate('VBOCHECKEDSTATUS'); ?></span>
465 </div>
466 <div class="vbo-bookdet-foot">
467 <button type="button" class="btn btn-small <?php echo $checked_btn; ?>" onclick="vboOpenJModal('vbo-checkin-booking', 'index.php?option=com_vikbooking&task=bookingcheckin&cid[]=<?php echo $row['id']; ?>&tmpl=component');">
468 <?php echo $checked_status; ?>
469 </button>
470 </div>
471 </div>
472 <?php
473 //Prepare modal (Registration)
474 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-checkin-booking', JText::translate('VBOMANAGECHECKSINOUT')));
475 //end Prepare modal
476 }
477
478 /**
479 * Check whether the booking can be refunded or charged through an off-session capturing.
480 *
481 * @since 1.14 (J) - 1.4.0 (WP)
482 * @since 1.18.0 (J) - 1.8.0 (WP) added support to off-session capturing.
483 */
484
485 // refundable/capturable up to 7 days after check-out day
486 $max_refund_ts = mktime(23, 59, 59, $checkout_info['mon'], ($checkout_info['mday'] + 7), $checkout_info['year']);
487
488 // current payment driver must be set
489 $tn_driver = is_array($payment) ? $payment['file'] : null;
490
491 // transaction data validation callback
492 $tn_data_callback = function($data) use ($tn_driver) {
493 return (is_object($data) && isset($data->driver) && basename($data->driver, '.php') == basename($tn_driver, '.php'));
494 };
495 $prev_tn_data = $history_obj->getEventsWithData(array('P0', 'PN'), $tn_data_callback);
496
497 // whether it's refundable/capturable
498 $refundable = ($row['status'] != 'standby' && !empty($row['totpaid']) && $max_refund_ts >= $current_ts && is_array($prev_tn_data) && $prev_tn_data);
499 $off_session_capturing = ($row['status'] != 'standby' && $max_refund_ts >= $current_ts && is_array($prev_tn_data) && array_filter($prev_tn_data, function($data) {
500 return is_object($data) && ($data->future_usage ?? null);
501 }));
502
503 if ($off_session_capturing) {
504 ?>
505 <div class="vbo-bookdet-wrap">
506 <div class="vbo-bookdet-head">
507 <span><?php echo JText::translate('VBO_CREDIT_CARD'); ?></span>
508 </div>
509 <div class="vbo-bookdet-foot">
510 <button type="button" class="btn btn-small vbo-config-btn vbo-offsessioncapture-btn" onclick="VBOCore.handleDisplayWidgetNotification({widget_id: 'virtual_terminal'}, {bid: <?php echo $row['id']; ?>});">
511 <?php VikBookingIcons::e('credit-card'); ?>
512 <?php echo JText::translate('VBO_W_VIRTUALTERMINAL_TITLE'); ?>
513 </button>
514 </div>
515 </div>
516 <?php
517 }
518
519 if ($refundable) {
520 // prepare modal (refundtn) with a custom function to trigger the opening
521 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-refund-tn', JText::translate('VBO_ISSUE_REFUND')));
522 echo $vbo_app->getJmodalScript('Refund', 'vboDetectRefundChanges();');
523 // count the number of refunds made
524 $refunds = $history_obj->getEventsWithData('RF', null, false);
525 $refunds = !is_array($refunds) ? array() : $refunds;
526 ?>
527 <script type="text/javascript">
528 var vbo_refund_performed = false;
529 function vboDetectRefundChanges() {
530 if (vbo_refund_performed === true) {
531 location.reload();
532 }
533 }
534 </script>
535
536 <div class="vbo-bookdet-wrap">
537 <div class="vbo-bookdet-head">
538 <span><?php echo JText::translate('VBO_ISSUE_REFUND'); ?></span>
539 </div>
540 <div class="vbo-bookdet-foot">
541 <button type="button" class="btn btn-small btn-danger vbo-dorefund-btn"<?php echo $refunds ? ' data-totrefunds="' . count($refunds) . '"' : ''; ?> onclick="vboOpenJModalRefund('vbo-refund-tn', 'index.php?option=com_vikbooking&task=refundtn&cid[]=<?php echo $row['id']; ?>&tmpl=component');">
542 <?php echo JText::translate('VBO_REFUND'); ?>
543 </button>
544 </div>
545 </div>
546 <?php
547 }
548
549 if (!$printreceipt && !empty($row['channel'])) {
550 $ota_logo_img = VikBooking::getVcmChannelsLogo($row['channel']);
551 if ($ota_logo_img === false) {
552 $ota_logo_img = $otachannel_name;
553 } else {
554 $ota_logo_img = '<img src="'.$ota_logo_img.'" class="vbo-channelimg-medium"/>';
555 }
556 ?>
557 <div class="vbo-bookdet-wrap">
558 <div class="vbo-bookdet-head">
559 <span><?php echo JText::translate('VBPVIEWORDERCHANNEL'); ?></span>
560 </div>
561 <div class="vbo-bookdet-foot">
562 <span><?php echo $ota_logo_img; ?></span>
563 </div>
564 </div>
565 <?php
566 } elseif (!$printreceipt && class_exists('VCMOtaBooking')) {
567 /**
568 * Vik Channel Manager booking assignable channels.
569 *
570 * @since 1.16.3 (J) - 1.6.3 (WP)
571 */
572 $assignable_channels = VCMOtaBooking::getInstance($row, true)->getChannelsAssignable();
573 if ($assignable_channels) {
574 JText::script('VBO_ASSIGN_BOOKING_TO_OTA_CONFIRM');
575 JFactory::getDocument()->addScriptDeclaration(
576 <<<JS
577 function vboConfirmAssignChannel(ch_key, ch_name) {
578 if (!ch_key || !ch_name) {
579 return true;
580 }
581 if (confirm(Joomla.JText._('VBO_ASSIGN_BOOKING_TO_OTA_CONFIRM').replace('%s', ch_name))) {
582 document.adminForm.submit();
583 return true;
584 } else {
585 return false;
586 }
587 }
588 JS
589 );
590 ?>
591 <div class="vbo-bookdet-wrap">
592 <div class="vbo-bookdet-head">
593 <span><?php echo JText::translate('VBPVIEWORDERCHANNEL'); ?></span>
594 </div>
595 <div class="vbo-bookdet-foot">
596 <select name="vcm_assign_channel" class="vbo-select-small" onchange="return vboConfirmAssignChannel(this.value, this.options[this.selectedIndex].text);">
597 <option value=""><?php echo JText::translate('VBORDFROMSITE'); ?></option>
598 <?php
599 foreach ($assignable_channels as $assign_ch_key => $assign_ch_name) {
600 ?>
601 <option value="<?php echo JHtml::fetch('esc_attr', $assign_ch_key); ?>"><?php echo $assign_ch_name; ?></option>
602 <?php
603 }
604 ?>
605 </select>
606 </div>
607 </div>
608 <?php
609 }
610 }
611 if (!$printreceipt) {
612 ?>
613 <div class="vbo-bookdet-wrap">
614 <div class="vbo-bookdet-head">
615 <span><?php echo JText::translate('VBSTATUS'); ?></span>
616 </div>
617 <div class="vbo-bookdet-foot">
618 <span><?php echo $saystaus; ?></span>
619 </div>
620 </div>
621 <?php
622 if (is_array($this->vcm_pre_approval)) {
623 ?>
624 <div class="vbo-bookdet-wrap">
625 <div class="vbo-bookdet-head">
626 <span><?php echo $this->vcm_pre_approval[1]; ?></span>
627 </div>
628 <div class="vbo-bookdet-foot">
629 <span>
630 <?php
631 if (empty($this->vcm_pre_approval[2]) || !empty($this->vcm_pre_approval[3])) {
632 // no pre-approvals before, or withdrawn before
633 ?>
634 <a href="index.php?option=com_vikchannelmanager&task=sendSpecialOffer&vbo_oid=<?php echo $row['id']; ?>&spo_type=preapproval&spo_action=send&ota_thread_id=<?php echo $this->vcm_pre_approval[0]; ?>" class="btn btn-small btn-primary vcm-btn-channel-<?php echo strtolower($this->vcm_pre_approval[1]); ?>"><?php VikBookingIcons::e('thumbs-up'); ?> <?php echo JText::translate('VBO_PREAPPROVE_INQUIRY'); ?></a>
635 <?php
636 } else {
637 // pre-approved before, pass the ID
638 ?>
639 <a href="index.php?option=com_vikchannelmanager&task=sendSpecialOffer&vbo_oid=<?php echo $row['id']; ?>&spo_type=preapproval&spo_action=withdraw&ota_thread_id=<?php echo $this->vcm_pre_approval[0]; ?>&spo_id=<?php echo $this->vcm_pre_approval[2]; ?>" class="btn btn-small btn-danger"><?php VikBookingIcons::e('thumbs-down'); ?> <?php echo JText::translate('VBO_WITHDRAW_PREAPPROVAL'); ?></a>
640 <?php
641 }
642 ?>
643 </span>
644 </div>
645 </div>
646 <?php
647 }
648 if (!empty($row['channel']) && stripos($row['channel'], 'booking.com') !== false && $row['checkin'] <= $current_ts && strtotime('+ 7 days', $row['checkout']) >= $current_ts) {
649 /**
650 * Guest misconduct reporting API for Booking.com.
651 * Only after reservation check-in date and no later than 7 days after check-out date.
652 *
653 * @since 1.13.5 - VCM 1.7.2
654 */
655 $misconduct_reported = $history_obj->hasEvent('GM');
656 ?>
657 <div class="vbo-bookdet-wrap">
658 <div class="vbo-bookdet-head">
659 <span><?php echo JText::translate('VBOGUESTMISCONDUCT'); ?></span>
660 </div>
661 <div class="vbo-bookdet-foot">
662 <?php
663 if ($misconduct_reported === false) {
664 // allow to report the guest misconduct
665 ?>
666 <button type="button" class="btn btn-small btn-danger" onclick="vboRenderGuestMisconduct();"><?php VikBookingIcons::e('user-slash'); ?> <?php echo JText::translate('VBOREPORTMISCONDUCT'); ?></button>
667 <?php
668 } else {
669 // guest misconduct already reported
670 ?>
671 <button type="button" class="btn btn-small btn-warning" onclick="vboShowGuestMisconductReported();"><?php VikBookingIcons::e('user-slash'); ?> <?php echo $misconduct_reported; ?></button>
672 <?php
673 }
674 ?>
675 <a id="vbo-gm-reloadlink" style="display: none;" href="index.php?option=com_vikbooking&task=editorder&cid[]=<?php echo $row['id']; ?>"></a>
676 </div>
677
678 <div class="vbo-modal-overlay-block vbo-modal-overlay-block-guestmisconduct">
679 <a class="vbo-modal-overlay-close" href="javascript: void(0);"></a>
680 <div class="vbo-modal-overlay-content vbo-modal-overlay-content-guestmisconduct">
681 <div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-head-guestmisconduct">
682 <h3><?php VikBookingIcons::e('exclamation-circle'); ?> <?php echo JText::sprintf('VBOREPGUESTMISCONDUCTTO', 'Booking.com'); ?> <span class="vbo-modal-overlay-close-times" onclick="hideVboDialogGuestMisconduct();">&times;</span></h3>
683 </div>
684 <div class="vbo-modal-overlay-content-body">
685 <div class="vbo-modal-guestmisconduct-addnew" data-bid="<?php echo $row['id']; ?>" data-otabid="<?php echo $row['idorderota']; ?>">
686 <div class="vbo-modal-guestmisconduct-report-elems"></div>
687 <div class="vbo-modal-guestmisconduct-addnew-save">
688 <button type="button" id="vbo-guest-misconduct-submit-btn" class="btn btn-success" onclick="vboSubmitGuestMisconduct();" style="display: none;"><?php echo JText::translate('VBCHANNELMANAGERSENDRQ'); ?></button>
689 <button type="button" class="btn btn-secondary" onclick="hideVboDialogGuestMisconduct();"><?php echo JText::translate('VBOCLOSE'); ?></button>
690 </div>
691 </div>
692 </div>
693 </div>
694 </div>
695
696 <script type="text/javascript">
697 var vbodialogguestmisconduct_on = false;
698 var vbo_guest_misconduct_fields = new Array;
699
700 function vboShowGuestMisconductReported() {
701 // this is like simulating the navigation to the booking history tab
702 jQuery(".vbo-bookingdet-tab[data-vbotab='vbo-tab-admin']").trigger('click');
703 vbToggleHistory(document.getElementById('vbo-trig-bookhistory'));
704 }
705
706 function vboRenderGuestMisconduct() {
707 // empty content
708 jQuery('.vbo-modal-guestmisconduct-report-elems').html('<?php echo $this->escape(JText::translate('VIKLOADING') . '...'); ?>');
709 vbo_guest_misconduct_fields = new Array;
710
711 // display modal
712 jQuery('.vbo-modal-overlay-block-guestmisconduct').fadeIn();
713 vbodialogguestmisconduct_on = true;
714
715 // make AJAX request to VCM to always reload the form fields
716 VBOCore.doAjax(
717 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikchannelmanager&task=get_bcom_misconduct_categories'); ?>",
718 {
719 tmpl: "component"
720 },
721 (res) => {
722 // parse the JSON response that contains the categories object with all fields for the reporting
723 try {
724 var misconduct_fields_rs = JSON.parse(res);
725
726 // make sure the request was successful
727 if (!misconduct_fields_rs.status) {
728 alert(misconduct_fields_rs.error);
729 hideVboDialogGuestMisconduct();
730 return false;
731 }
732
733 // render form from response obtained
734 var misconduct_html = '';
735 var misconduct_fields = misconduct_fields_rs.data;
736 if (!misconduct_fields.hasOwnProperty('categories') || !misconduct_fields.hasOwnProperty('fields')) {
737 alert('Unexptected response. Vik Channel Manager needs to be installed, configured and updated to the latest version.');
738 hideVboDialogGuestMisconduct();
739 return false;
740 }
741
742 // main category of misconduct
743 misconduct_html += '<div class="vbo-modal-form-addnew-elem vbo-modal-guestmisconduct-addnew-elem">' + "\n";
744 misconduct_html += '<label for="vbo-gm-category">' + misconduct_fields['labels']['category'] + '</label>';
745 misconduct_html += '<select id="vbo-gm-category" data-gmname="category_id" onchange="vboGuestMisconductChangeCategory(this.value);">' + "\n";
746 for (var category in misconduct_fields['categories']) {
747 if (!misconduct_fields['categories'].hasOwnProperty(category)) {
748 continue;
749 }
750 misconduct_html += '<option value="' + misconduct_fields['categories'][category]['id'] + '">' + misconduct_fields['categories'][category]['title'] + '</option>' + "\n";
751 }
752 misconduct_html += '</select>' + "\n";
753 misconduct_html += '</div>' + "\n";
754 // push category field in fields list for later submit
755 vbo_guest_misconduct_fields.push('vbo-gm-category');
756
757 // sub-categories or additional fields of misconduct categories
758 for (var category in misconduct_fields['categories']) {
759 if (!misconduct_fields['categories'].hasOwnProperty(category)) {
760 continue;
761 }
762 if (!misconduct_fields['categories'][category].hasOwnProperty('subcategories') && !misconduct_fields['categories'][category].hasOwnProperty('additional_fields')) {
763 // at least one of these two properties must be set
764 continue;
765 }
766 if (misconduct_fields['categories'][category].hasOwnProperty('subcategories') && misconduct_fields['categories'][category]['subcategories'].length) {
767 // sub-categories in drop down
768 var subcat_field_id = 'vbo-gm-subcategory' + misconduct_fields['categories'][category]['id'];
769 misconduct_html += '<div class="vbo-modal-form-addnew-elem vbo-modal-guestmisconduct-addnew-elem vbo-modal-guestmisconduct-addnew-cond" data-gmcid="' + misconduct_fields['categories'][category]['id'] + '" style="display: none;">' + "\n";
770 misconduct_html += '<label for="' + subcat_field_id + '">' + misconduct_fields['labels']['subcategory'] + '</label>';
771 misconduct_html += '<select id="' + subcat_field_id + '" data-gmname="subcategory_id">' + "\n";
772 for (var subcategory in misconduct_fields['categories'][category]['subcategories']) {
773 if (!misconduct_fields['categories'][category]['subcategories'].hasOwnProperty(subcategory)) {
774 continue;
775 }
776 misconduct_html += '<option value="' + misconduct_fields['categories'][category]['subcategories'][subcategory]['id'] + '">' + misconduct_fields['categories'][category]['subcategories'][subcategory]['title'] + '</option>' + "\n";
777 }
778 misconduct_html += '</select>' + "\n";
779 misconduct_html += '</div>' + "\n";
780 // push sub-category field in fields list for later submit
781 if (vbo_guest_misconduct_fields.indexOf(subcat_field_id) < 0) {
782 vbo_guest_misconduct_fields.push(subcat_field_id);
783 }
784 } else if (misconduct_fields['categories'][category].hasOwnProperty('additional_fields') && misconduct_fields['categories'][category]['additional_fields'].length) {
785 // additional fields
786 for (var extra_field in misconduct_fields['categories'][category]['additional_fields']) {
787 if (!misconduct_fields['categories'][category]['additional_fields'].hasOwnProperty(extra_field)) {
788 continue;
789 }
790 var field_id = 'vbo-gm-extrafield-' + misconduct_fields['categories'][category]['additional_fields'][extra_field]['name'];
791 var field_name = misconduct_fields['categories'][category]['additional_fields'][extra_field]['name'];
792 misconduct_html += '<div class="vbo-modal-form-addnew-elem vbo-modal-guestmisconduct-addnew-elem vbo-modal-guestmisconduct-addnew-cond" data-gmcid="' + misconduct_fields['categories'][category]['id'] + '" style="display: none;">' + "\n";
793 misconduct_html += '<label for="' + field_id + '">' + misconduct_fields['categories'][category]['additional_fields'][extra_field]['label'] + '</label>';
794 if (misconduct_fields['categories'][category]['additional_fields'][extra_field]['type'] == 'number') {
795 misconduct_html += '<input data-gmname="' + field_name + '" type="number" id="' + field_id + '" value="" step="any" min="0" />';
796 } else if (misconduct_fields['categories'][category]['additional_fields'][extra_field]['type'] == 'text') {
797 misconduct_html += '<input data-gmname="' + field_name + '" type="text" id="' + field_id + '" value="" />';
798 } else if (misconduct_fields['categories'][category]['additional_fields'][extra_field]['type'] == 'text') {
799 misconduct_html += '<input data-gmname="' + field_name + '" type="text" id="' + field_id + '" value="" />';
800 } else if (misconduct_fields['categories'][category]['additional_fields'][extra_field]['type'] == 'textarea') {
801 misconduct_html += '<textarea data-gmname="' + field_name + '" id="' + field_id + '" rows="5" cols="50" maxlength="240"></textarea>';
802 } else if (misconduct_fields['categories'][category]['additional_fields'][extra_field]['type'] == 'select') {
803 misconduct_html += '<select data-gmname="' + field_name + '" id="' + field_id + '">';
804 for (var choicekey in misconduct_fields['categories'][category]['additional_fields'][extra_field]['choices']) {
805 // this is either an array when keys are numeric from 0, or an object when keys start from like 1, but with choicekey we take the proper key in the object
806 if (!misconduct_fields['categories'][category]['additional_fields'][extra_field]['choices'].hasOwnProperty(choicekey)) {
807 continue;
808 }
809 misconduct_html += '<option value="' + choicekey + '">' + misconduct_fields['categories'][category]['additional_fields'][extra_field]['choices'][choicekey] + '</option>';
810 }
811 misconduct_html += '</select>';
812 }
813 misconduct_html += '</div>' + "\n";
814 // push additional field in fields list for later submit
815 vbo_guest_misconduct_fields.push(field_id);
816 }
817 }
818 }
819
820 // mandatory fields for all categories of guest misconduct reporting
821 for (var mandfield in misconduct_fields['fields']) {
822 if (!misconduct_fields['fields'].hasOwnProperty(mandfield)) {
823 continue;
824 }
825 var field_id = 'vbo-gm-mandfield-' + misconduct_fields['fields'][mandfield]['name'];
826 var field_name = misconduct_fields['fields'][mandfield]['name'];
827 misconduct_html += '<div class="vbo-modal-form-addnew-elem vbo-modal-guestmisconduct-addnew-elem">' + "\n";
828 misconduct_html += '<label for="' + field_id + '">' + misconduct_fields['fields'][mandfield]['label'] + '</label>';
829 if (misconduct_fields['fields'][mandfield]['type'] == 'number') {
830 misconduct_html += '<input data-gmname="' + field_name + '" type="number" id="' + field_id + '" value="" step="any" min="0" />';
831 } else if (misconduct_fields['fields'][mandfield]['type'] == 'text') {
832 misconduct_html += '<input data-gmname="' + field_name + '" type="text" id="' + field_id + '" value="" />';
833 } else if (misconduct_fields['fields'][mandfield]['type'] == 'text') {
834 misconduct_html += '<input data-gmname="' + field_name + '" type="text" id="' + field_id + '" value="" />';
835 } else if (misconduct_fields['fields'][mandfield]['type'] == 'textarea') {
836 misconduct_html += '<textarea data-gmname="' + field_name + '" id="' + field_id + '" rows="5" cols="50" maxlength="240"></textarea>';
837 } else if (misconduct_fields['fields'][mandfield]['type'] == 'select') {
838 misconduct_html += '<select data-gmname="' + field_name + '" id="' + field_id + '">';
839 for (var choicekey in misconduct_fields['fields'][mandfield]['choices']) {
840 if (!misconduct_fields['fields'][mandfield]['choices'].hasOwnProperty(choicekey)) {
841 continue;
842 }
843 misconduct_html += '<option value="' + choicekey + '">' + misconduct_fields['fields'][mandfield]['choices'][choicekey] + '</option>';
844 }
845 misconduct_html += '</select>';
846 }
847 misconduct_html += '</div>' + "\n";
848 // push mandatory field in fields list for later submit
849 vbo_guest_misconduct_fields.push(field_id);
850 }
851
852 // display HTML content and submit button
853 jQuery('.vbo-modal-guestmisconduct-report-elems').html(misconduct_html);
854 jQuery('#vbo-guest-misconduct-submit-btn').show();
855 // trigger change of main category drop down
856 jQuery('#vbo-gm-category').trigger('change');
857 } catch (e) {
858 console.log(res);
859 alert('Invalid response. Vik Channel Manager needs to be installed, configured and updated to the latest version.');
860 hideVboDialogGuestMisconduct();
861 return false;
862 }
863 },
864 (err) => {
865 hideVboDialogGuestMisconduct();
866 alert('Request failed. Vik Channel Manager needs to be installed, configured and updated to the latest version.');
867 }
868 );
869 }
870
871 function vboSubmitGuestMisconduct() {
872 if (!vbo_guest_misconduct_fields.length) {
873 alert('Empty data to submit. Vik Channel Manager needs to be installed, configured and updated to the latest version.');
874 return false;
875 }
876
877 // prevent double submissions
878 vboGuestMisconductDisableSubmit();
879 //
880
881 var submit_fields = {
882 tmpl: "component",
883 bid: jQuery('.vbo-modal-guestmisconduct-addnew').attr('data-bid'),
884 otabid: jQuery('.vbo-modal-guestmisconduct-addnew').attr('data-otabid'),
885 bcom_keys: new Array
886 };
887 for (var elemid in vbo_guest_misconduct_fields) {
888 if (!vbo_guest_misconduct_fields.hasOwnProperty(elemid)) {
889 continue;
890 }
891 if (!jQuery('#' + vbo_guest_misconduct_fields[elemid]).length || !jQuery('#' + vbo_guest_misconduct_fields[elemid]).closest('.vbo-modal-guestmisconduct-addnew-elem').length) {
892 // form element not found, or parent container not found
893 continue;
894 }
895 if (jQuery('#' + vbo_guest_misconduct_fields[elemid]).closest('.vbo-modal-guestmisconduct-addnew-elem').is(':visible')) {
896 // we include this value in the AJAX request
897 var field_name = jQuery('#' + vbo_guest_misconduct_fields[elemid]).attr('data-gmname');
898 var submit_key = 'bcom_' + field_name;
899 submit_fields[submit_key] = jQuery('#' + vbo_guest_misconduct_fields[elemid]).val();
900 submit_fields['bcom_keys'].push(submit_key);
901 }
902 }
903
904 // make the AJAX request to VCM
905 var jqxhr = jQuery.ajax({
906 type: "POST",
907 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikchannelmanager&task=submit_bcom_guestmisconduct'); ?>",
908 data: submit_fields
909 }).done(function(res) {
910 try {
911 var misconduct_rs = JSON.parse(res);
912 console.log(submit_fields, misconduct_rs);
913
914 // make sure the request was successful
915 if (!misconduct_rs.status) {
916 alert(misconduct_rs.error);
917 vboGuestMisconductEnableSubmit();
918 return false;
919 }
920
921 // make another AJAX request (now on VBO) to update the booking history
922 var event_descr = jQuery('#vbo-gm-mandfield-details_text').length ? jQuery('#vbo-gm-mandfield-details_text').val() : '';
923 jQuery.ajax({
924 type: "POST",
925 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=store_booking_history_event'); ?>",
926 data: {
927 tmpl: "component",
928 bid: jQuery('.vbo-modal-guestmisconduct-addnew').attr('data-bid'),
929 event: 'GM',
930 descr: event_descr
931 }
932 }).done(function(res) {
933 // just reload the page in case of success
934 document.location.href = jQuery('#vbo-gm-reloadlink').attr('href');
935 }).fail(function() {
936 // we reload the page even in case of failure
937 document.location.href = jQuery('#vbo-gm-reloadlink').attr('href');
938 });
939 } catch (e) {
940 console.log(res);
941 alert('Invalid update response. Vik Channel Manager needs to be installed, configured and updated to the latest version.');
942 vboGuestMisconductEnableSubmit();
943 hideVboDialogGuestMisconduct();
944 return false;
945 }
946 }).fail(function() {
947 alert('Update Request failed. Vik Channel Manager needs to be installed, configured and updated to the latest version.');
948 vboGuestMisconductEnableSubmit();
949 return false;
950 });
951 }
952
953 function hideVboDialogGuestMisconduct() {
954 if (vbodialogguestmisconduct_on === true) {
955 jQuery(".vbo-modal-overlay-block-guestmisconduct").fadeOut(400, function () {
956 jQuery(".vbo-modal-overlay-content-guestmisconduct").show();
957 });
958 // turn flag off
959 vbodialogguestmisconduct_on = false;
960 }
961 }
962
963 function vboGuestMisconductChangeCategory(gmcid) {
964 jQuery('.vbo-modal-guestmisconduct-addnew-cond').each(function() {
965 if (jQuery(this).attr('data-gmcid') == gmcid) {
966 jQuery(this).show();
967 } else {
968 jQuery(this).hide();
969 }
970 });
971 }
972
973 function vboGuestMisconductDisableSubmit() {
974 jQuery('#vbo-guest-misconduct-submit-btn').prepend('<i class="<?php echo VikBookingIcons::i('refresh', 'fa-spin fa-fw'); ?>"></i> ').prop('disabled', true);
975 }
976
977 function vboGuestMisconductEnableSubmit() {
978 jQuery('#vbo-guest-misconduct-submit-btn').prop('disabled', false).find('i').remove();
979 }
980 </script>
981
982 </div>
983 <?php
984 }
985 if ($this->vcm_host_to_guest_review) {
986 ?>
987 <div class="vbo-bookdet-wrap">
988 <div class="vbo-bookdet-head">
989 <span><?php echo JText::translate('VBO_REVIEW_YOUR_GUEST'); ?></span>
990 </div>
991 <div class="vbo-bookdet-foot">
992 <button type="button" class="btn btn-small btn-primary vcm-btn-channel-airbnbapi" onclick="vboOpenJModal('vbo-vcm-host-to-guest-review', 'index.php?option=com_vikchannelmanager&task=hostguestreview&cid[]=<?php echo $row['id']; ?>&tmpl=component');">
993 <?php VikBookingIcons::e('smile'); ?>
994 <?php echo JText::translate('VBO_WRITE_REVIEW'); ?>
995 </button>
996 </div>
997 </div>
998 <?php
999 // prepare modal (host-to-guest review)
1000 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-host-to-guest-review', JText::translate('VBO_REVIEW_YOUR_GUEST')));
1001
1002 // check if a notification was clicked
1003 if (VikRequest::getString('notif_action', '', 'request') == 'airbnb_host_guest_review') {
1004 JFactory::getDocument()->addScriptDeclaration(
1005 <<<JS
1006 jQuery(function() {
1007 setTimeout(() => {
1008 jQuery('.vcm-btn-channel-airbnbapi').trigger('click');
1009 }, 500);
1010 });
1011 JS
1012 );
1013 }
1014 }
1015 }
1016 ?>
1017 </div>
1018
1019 <?php
1020 if (!$printreceipt && $this->allows_conversion !== false) {
1021 ?>
1022 <div class="vbo-bookdet-container vbo-bookdet-conv-currency">
1023 <div class="vbo-bookdet-conv-currency-inner">
1024 <div class="vbo-bookdet-conv-currency-info">
1025 <span><?php echo JText::sprintf('VBO_CONV_RES_OTA_CURRENCY', $this->conv_from_currency, $this->conv_to_currency); ?></span>
1026 <span><?php echo JText::sprintf('VBO_CONV_RES_OTA_CURRENCY_EXC', ($this->conv_from_currency . ' ' . VikBooking::numberFormat($row['total'])), ($this->conv_to_currency . ' ' . VikBooking::numberFormat($this->allows_conversion))); ?></span>
1027 </div>
1028 <div class="vbo-bookdet-conv-currency-apply">
1029 <a class="btn vbo-config-btn" onclick="return confirm(Joomla.JText._('VBO_CONV_RES_OTA_CURRENCY_APPLY') + '?');" href="index.php?option=com_vikbooking&task=editorder&cid[]=<?php echo $row['id']; ?>&do_ota_curr_conv=1"><?php VikBookingIcons::e('exchange-alt'); ?> <?php echo JText::translate('VBO_CONV_RES_OTA_CURRENCY_APPLY'); ?></a>
1030 </div>
1031 </div>
1032 </div>
1033 <?php
1034 }
1035
1036 if (!$printreceipt && $row['status'] == "standby" && empty($row['idorderota']) && !strcasecmp((string)$row['type'], 'Inquiry')) {
1037 // website pending reservation inquiry
1038 $ir_data_callback = function($data) {
1039 return (is_object($data) && !empty($data->av_type));
1040 };
1041 $prev_ir_data = $history_obj->getEventsWithData('IR', $ir_data_callback, true);
1042 if (is_array($prev_ir_data) && $prev_ir_data) {
1043 // display a message about the availability type at the time of creation of the inquiry reservation
1044
1045 // parse original stay dates into DateTime objects
1046 $orig_checkin_dt_obj = new JDate($prev_ir_data[0]->checkin_date);
1047 $orig_checkout_dt_obj = new JDate($prev_ir_data[0]->checkout_date);
1048 ?>
1049 <div class="vbo-bookdet-container vbo-bookdet-inquiry-alert">
1050 <div class="vbo-bookdet-inquiry-alert-dismiss">
1051 <button type="button" class="btn btn-warning" onclick="jQuery('.vbo-bookdet-inquiry-alert').remove();"><?php VikBookingIcons::e('times-circle'); ?> <?php echo JText::translate('VBOBTNKEEPREMIND'); ?></button>
1052 </div>
1053 <div class="vbo-bookdet-inquiry-alert-message">
1054 <div class="vbo-bookdet-inquiry-alert-top">
1055 <span><?php echo JText::translate('VBO_WEB_INQUIRY_ALERT'); ?></span>
1056 </div>
1057 <div class="vbo-bookdet-inquiry-alert-avtype">
1058 <span class="vbo-bookdet-inquiry-alert-mess-avtype"><?php
1059 // explain what was the availability at the time of inquiry
1060 if ($prev_ir_data[0]->av_type === 1) {
1061 echo JText::translate('VBO_WEB_INQUIRY_AVTYPE_1');
1062 } elseif ($prev_ir_data[0]->av_type === 2) {
1063 echo JText::translate('VBO_WEB_INQUIRY_AVTYPE_2');
1064 } elseif ($prev_ir_data[0]->av_type === 3) {
1065 echo JText::translate('VBO_WEB_INQUIRY_AVTYPE_3');
1066 } else {
1067 echo JText::translate('VBO_WEB_INQUIRY_AVTYPE_4');
1068 }
1069 ?></span>
1070 <span class="vbo-bookdet-inquiry-alert-mess-origrq">
1071 <strong><?php echo JText::translate('VBO_WEB_INQUIRY_ORIGRQ') . ':'; ?></strong>
1072 <span class="badge"><?php echo JText::translate('VBPICKUPAT') . ': ' . $orig_checkin_dt_obj->format('D, d M Y', true); ?></span>
1073 <span class="badge"><?php echo JText::translate('VBRELEASEAT') . ': ' . $orig_checkout_dt_obj->format('D, d M Y', true); ?></span>
1074 <span class="badge"><?php echo JText::translate('VBEDITORDERADULTS') . ': ' . $prev_ir_data[0]->adults; ?></span>
1075 <?php
1076 if (!empty($prev_ir_data[0]->children)) {
1077 ?>
1078 <span class="badge"><?php echo JText::translate('VBEDITORDERCHILDREN') . ': ' . $prev_ir_data[0]->children; ?></span>
1079 <?php
1080 }
1081 ?>
1082 </span>
1083 </div>
1084 <div class="vbo-bookdet-inquiry-alert-bottom">
1085 <span><?php echo JText::translate('VBO_WEB_INQUIRY_SUGG'); ?></span>
1086 </div>
1087 </div>
1088 </div>
1089 <?php
1090 }
1091 }
1092 ?>
1093
1094 <div class="vbo-bookingdet-innertop">
1095 <div class="vbo-bookingdet-commands">
1096 <?php
1097 if ($busy || $row['status'] == "standby") {
1098 ?>
1099 <div class="vbo-bookingdet-command">
1100 <button onclick="document.location.href='index.php?option=com_vikbooking&task=editbusy&cid[]=<?php echo $row['id']; ?>';" class="btn vbo-config-btn" type="button"><i class="icon-pencil"></i> <?php echo JText::translate('VBMODRES'); ?></button>
1101 </div>
1102 <?php
1103 }
1104 if ((array_key_exists(1, $tars) && $tars[1]) || ($is_package || $is_cust_cost)) {
1105
1106 if (VBOPlatformDetection::isWordPress()) {
1107 /**
1108 * @wponly display warning message if no valid Shortcodes found
1109 */
1110 $model = JModel::getInstance('vikbooking', 'shortcodes');
1111 $itemid = $model->best('booking');
1112 if (!$itemid) {
1113 VikError::raiseWarning('', 'No Shortcodes found, or no Shortcodes being used in Pages/Posts.');
1114 }
1115 }
1116
1117 ?>
1118 <div class="vbo-bookingdet-command">
1119 <button onclick="window.open('<?php echo VikBooking::externalroute('index.php?option=com_vikbooking&view=booking&sid='.(!empty($row['sid']) ? $row['sid'] : $row['idorderota']).'&ts='.$row['ts'], false); ?>', '_blank');" type="button" class="btn vbo-config-btn"><?php VikBookingIcons::e('external-link'); ?> <?php echo JText::translate('VBVIEWORDFRONT'); ?></button>
1120 </div>
1121 <?php
1122 }
1123 if (($row['status'] == "confirmed" || ($row['status'] == "standby" && !empty($row['custmail']))) && ((array_key_exists(1, $tars) && $tars[1]) || ($is_package || $is_cust_cost))) {
1124 ?>
1125 <div class="vbo-bookingdet-command">
1126 <button class="btn vbo-config-btn" type="button" onclick="document.location.href='index.php?option=com_vikbooking&task=resendordemail&cid[]=<?php echo $row['id']; ?>';"><?php VikBookingIcons::e('envelope'); ?> <?php echo JText::translate('VBRESENDORDEMAIL'); ?></button>
1127 </div>
1128 <?php
1129 }
1130 if (is_array($this->vcm_special_offer)) {
1131 if (empty($this->vcm_special_offer[3]) || !empty($this->vcm_special_offer[4])) {
1132 // no special offer sent before, or withdrawn
1133 ?>
1134 <div class="vbo-bookingdet-command">
1135 <button type="button" class="btn btn-primary vcm-btn-channel-<?php echo strtolower($this->vcm_special_offer[2]); ?>" onclick="vboOpenJModal('vbo-vcm-special-offer', 'index.php?option=com_vikchannelmanager&task=specialoffer&bid=<?php echo $row['id']; ?>&listing_id=<?php echo $this->vcm_special_offer[0]; ?>&ota_thread_id=<?php echo $this->vcm_special_offer[1]; ?>&tmpl=component');"><?php VikBookingIcons::e('certificate'); ?> <?php echo JText::sprintf('VBO_VCM_SPECIAL_OFFER', $this->vcm_special_offer[2]); ?></button>
1136 </div>
1137 <?php
1138 // prepare modal (VCM prepare special offer)
1139 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-special-offer', JText::sprintf('VBO_VCM_SPECIAL_OFFER', $this->vcm_special_offer[2])));
1140 // end prepare modal
1141 } else {
1142 // special offer sent before, link to withdraw it
1143 ?>
1144 <div class="vbo-bookingdet-command">
1145 <a href="index.php?option=com_vikchannelmanager&task=sendSpecialOffer&vbo_oid=<?php echo $row['id']; ?>&spo_type=special_offer&spo_action=withdraw&ota_thread_id=<?php echo $this->vcm_special_offer[1]; ?>&spo_id=<?php echo $this->vcm_special_offer[3]; ?>" class="btn btn-danger"><?php VikBookingIcons::e('ban'); ?> <?php echo JText::translate('VBO_WITHDRAW_SPOFFER'); ?></a>
1146 </div>
1147 <?php
1148 }
1149 }
1150 if ($row['status'] == "standby" || ($row['status'] == "cancelled" && $row['checkout'] >= $current_ts)) {
1151 ?>
1152 <div class="vbo-bookingdet-command">
1153 <button class="btn btn-success" type="button" onclick="if (confirm('<?php echo htmlspecialchars(JText::translate('VBSETORDCONFIRMED')); ?> ?')) {document.location.href='index.php?option=com_vikbooking&task=setordconfirmed&cid[]=<?php echo $row['id'] . ($row['status'] == "cancelled" ? '&skip_notification=1' : ''); ?>';}"><?php VikBookingIcons::e('check'); ?> <?php echo JText::translate('VBSETORDCONFIRMED'); ?></button>
1154 </div>
1155 <?php
1156 }
1157 if ($row['status'] == "cancelled" && !$row['closure']) {
1158 ?>
1159 <div class="vbo-bookingdet-command">
1160 <button type="button" class="btn btn-warning vbo-context-menu-btn vbo-context-menu-actionscanc">
1161 <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBCRONACTIONS'); ?></span>
1162 <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('sort-down'); ?></span>
1163 </button>
1164 </div>
1165
1166 <script type="text/javascript">
1167 jQuery(function() {
1168 jQuery('.vbo-context-menu-actionscanc').vboContextMenu({
1169 placement: 'bottom-right',
1170 buttons: [
1171 <?php
1172 if (!empty($row['custmail'])) :
1173 ?>
1174 {
1175 icon: '<?php echo VikBookingIcons::i('envelope'); ?>',
1176 text: Joomla.JText._('VBSENDCANCORDEMAIL'),
1177 class: 'vbo-context-menu-entry-danger',
1178 separator: true,
1179 action: (root, config) => {
1180 document.location.href = 'index.php?option=com_vikbooking&task=sendcancordemail&cid[]=<?php echo $row['id']; ?>';
1181 },
1182 },
1183 <?php
1184 endif;
1185 ?>
1186 {
1187 icon: '<?php echo VikBookingIcons::i('hourglass-half'); ?>',
1188 text: Joomla.JText._('VBO_SET_STANDBY'),
1189 class: 'vbo-context-menu-entry-warning',
1190 separator: false,
1191 action: (root, config) => {
1192 document.location.href = '<?php echo VBOFactory::getPlatform()->getUri()->addCSRF('index.php?option=com_vikbooking&task=bookings.set_to_pending&bid=' . $row['id']); ?>';
1193 },
1194 },
1195 ],
1196 });
1197 });
1198 </script>
1199 <?php
1200 }
1201 if ($row['status'] == 'confirmed' && $row['closure'] < 1) {
1202 ?>
1203 <div class="vbo-bookingdet-command pro-feature">
1204 <button type="button" class="btn vbo-config-btn" onclick="document.getElementById('invnotes-hid').value=document.getElementById('invnotes').value;document.getElementById('vbo-gen-invoice').submit();"><?php VikBookingIcons::e('file-text-o'); ?> <?php echo JText::translate('VBOGENBOOKINGINVOICE'); ?></button>
1205 </div>
1206 <?php
1207 }
1208 if ($row['status'] == 'confirmed' && $row['closure'] < 1) {
1209 ?>
1210 <div class="vbo-bookingdet-command pro-feature">
1211 <button type="button" class="btn vbo-config-btn" onclick="window.open('index.php?option=com_vikbooking&task=editorder&cid[]=<?php echo $row['id']; ?>&print=1&tmpl=component', '_blank');"><?php VikBookingIcons::e('print'); ?> <?php echo JText::translate('VBOPRINTRECEIPT'); ?></button>
1212 </div>
1213 <?php
1214 }
1215 if ($row['status'] != 'confirmed' || $row['closure'] > 0 || $this->vcm_cancel_active_res) {
1216 if ($this->vcm_decline_actions) {
1217 // this booking requires some decline actions before being removed
1218 ?>
1219 <div class="vbo-bookingdet-command">
1220 <button type="button" class="btn btn-danger" onclick="vboOpenJModal('vbo-vcm-decline-booking', 'index.php?option=com_vikchannelmanager&task=declinebooking&cid[]=<?php echo $row['id']; ?>&tmpl=component');"><?php VikBookingIcons::e('trash'); ?> <?php echo JText::translate('VBMAINEBUSYDEL'); ?></button>
1221 </div>
1222 <?php
1223 // prepare modal (VCM decline booking)
1224 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-decline-booking', JText::translate('VBMAINEBUSYDEL')));
1225 // end prepare modal
1226 } elseif ($this->vcm_cancel_active_res) {
1227 // the active OTA booking can be cancelled
1228 ?>
1229 <div class="vbo-bookingdet-command">
1230 <button type="button" class="btn btn-danger" onclick="vboOpenJModal('vbo-vcm-cancel-reservation', 'index.php?option=com_vikchannelmanager&task=cancelreservation&vbo_oid=<?php echo $row['id']; ?>&tmpl=component');"><?php VikBookingIcons::e('trash'); ?> <?php echo JText::translate('VBMAINEBUSYDEL'); ?></button>
1231 </div>
1232 <?php
1233 // prepare modal (VCM cancel reservation)
1234 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-cancel-reservation', JText::translate('VBMAINEBUSYDEL')));
1235 // end prepare modal
1236 } else {
1237 // regular remove button with confirmation
1238 ?>
1239 <div class="vbo-bookingdet-command">
1240 <button type="button" class="btn btn-danger" onclick="if (confirm(Joomla.JText._('VBDELCONFIRM'))){document.location.href='index.php?option=com_vikbooking&task=removeorders&cid[]=<?php echo $row['id']; ?>&goto=<?php echo $row['id']; ?>';}"><?php VikBookingIcons::e('trash'); ?> <?php echo $row['status'] == 'cancelled' ? JText::translate('VBO_PURGERM_RESERVATION') : JText::translate('VBMAINEBUSYDEL'); ?></button>
1241 </div>
1242 <?php
1243 }
1244 }
1245 ?>
1246
1247 <!-- Define role to detect the supported hook -->
1248 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorder","key":"buttons","type":"field"} -->
1249
1250 <?php
1251 if (isset($bookingPanelForms['buttons']))
1252 {
1253 echo $bookingPanelForms['buttons'];
1254 }
1255 ?>
1256 </div>
1257
1258 <div class="vbo-bookingdet-tabs">
1259 <div class="vbo-bookingdet-tab vbo-bookingdet-tab-active" data-vbotab="vbo-tab-details"><?php echo JText::translate('VBOBOOKDETTABDETAILS'); ?></div>
1260 <div class="vbo-bookingdet-tab" data-vbotab="vbo-tab-admin"><?php echo JText::translate('VBOBOOKDETTABADMIN'); ?></div>
1261 </div>
1262 </div>
1263
1264 <?php
1265 /**
1266 * Check if the booking has got some tasks assigned.
1267 *
1268 * @since 1.18.0 (J) - 1.8.0 (WP)
1269 */
1270 $taskManager = VBOFactory::getTaskManager();
1271 $bookingTasks = VBOTaskModelTask::getInstance()->filterItems(['id_order' => $row['id']]);
1272 ?>
1273
1274 <div class="vbo-bookingdet-tab-cont" id="vbo-tab-details" style="display: block;">
1275 <div class="vbo-bookingdet-innercontainer">
1276 <div class="vbo-bookingdet-customer">
1277 <?php
1278 if ($bookingTasks) {
1279 ?>
1280 <div class="vbo-bookingdet-detcont vbo-bookingdet-detcont-tm vbo-hidein-print">
1281 <div class="vbo-bookingdet-lblcont">
1282 <label><?php echo JText::translate('VBO_TASK_MANAGER'); ?></label>
1283 </div>
1284 <div class="vbo-bookingdet-inpwrap vbo-bookingdet-tasks-list">
1285 <?php
1286 foreach ($bookingTasks as $taskRecord) {
1287 $task = VBOTaskTaskregistry::getInstance((array) $taskRecord);
1288 ?>
1289 <div class="vbo-bookingdet-task-details" data-task-id="<?php echo $task->getID(); ?>">
1290 <div class="vbo-bookingdet-task-detail" data-type="info">
1291 <span class="vbo-bookingdet-task-title"><?php echo $task->getTitle(); ?></span>
1292 <span class="vbo-bookingdet-task-sub-title"><?php echo $task->getAreaName($task->getAreaID()); ?></span>
1293 </div>
1294 <?php
1295 $taskUnreadMessages = (bool) $task->get('hasUnreadMessages', false);
1296 if ($taskUnreadMessages) {
1297 ?>
1298 <div class="vbo-bookingdet-task-detail" data-type="unread-messages">
1299 <span class="unread-message-dot"><?php VikBookingIcons::e('comment'); ?></span>
1300 </div>
1301 <?php
1302 }
1303 if ($taskManager->statusTypeExists($task->getStatus())) {
1304 $taskStatus = $taskManager->getStatusTypeInstance($task->getStatus());
1305 ?>
1306 <div class="vbo-bookingdet-task-detail" data-type="status">
1307 <span class="vbo-tm-task-status-badge vbo-tm-color <?php echo $taskStatus->getColor(); ?>" data-status="<?php echo $this->escape($taskStatus->getEnum()); ?>"><?php echo $taskStatus->getName(); ?></span>
1308 </div>
1309 <?php
1310 }
1311 ?>
1312 </div>
1313 <?php
1314 }
1315 ?>
1316 </div>
1317 </div>
1318 <?php
1319 }
1320 ?>
1321 <div class="vbo-bookingdet-detcont<?php echo $row['closure'] > 0 ? ' vbo-bookingdet-closure' : ''; ?>">
1322 <?php
1323 $custdata_parts = explode("\n", $row['custdata']);
1324 if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) {
1325 //attempt to format labels and values
1326 foreach ($custdata_parts as $custdet) {
1327 if (strlen($custdet) < 1) {
1328 continue;
1329 }
1330 $custdet_parts = explode(':', $custdet);
1331 $custd_lbl = '';
1332 $custd_val = '';
1333 if (count($custdet_parts) < 2) {
1334 $custd_val = $custdet;
1335 } else {
1336 $custd_lbl = $custdet_parts[0];
1337 if ($custd_lbl == 'http' || $custd_lbl == 'https') {
1338 // shift values
1339 $custdet_parts[2] = $custdet_parts[1];
1340 $custdet_parts[1] = $custdet_parts[0];
1341 $custd_lbl = '';
1342 }
1343 unset($custdet_parts[0]);
1344 if ((!strcasecmp(trim($custdet_parts[1]), 'http') || !strcasecmp(trim($custdet_parts[1]), 'https')) && !empty($custdet_parts[2]) && strpos($custdet_parts[2], '//') !== false) {
1345 // this is a URI
1346 $custd_val = '<a href="' . trim(implode(':', $custdet_parts)) . '" target="_blank"><i class="' . VikBookingIcons::i('external-link') . '"></i></a>';
1347 } else {
1348 $custd_val = trim(implode(':', $custdet_parts));
1349 }
1350 }
1351 ?>
1352 <div class="vbo-bookingdet-userdetail">
1353 <?php
1354 if (strlen($custd_lbl)) {
1355 ?>
1356 <span class="vbo-bookingdet-userdetail-lbl"><?php echo VikBooking::tnCustomerRawDataLabel($custd_lbl); ?></span>
1357 <?php
1358 }
1359 if (strlen($custd_val)) {
1360 ?>
1361 <span class="vbo-bookingdet-userdetail-val"><?php echo $custd_val; ?></span>
1362 <?php
1363 }
1364 ?>
1365 </div>
1366 <?php
1367 }
1368 } else {
1369 if ($row['closure'] > 0) {
1370 ?>
1371 <div class="vbo-bookingdet-userdetail">
1372 <span class="vbo-bookingdet-userdetail-val"><?php echo nl2br($row['custdata']); ?></span>
1373 </div>
1374 <?php
1375 } else {
1376 echo nl2br($row['custdata']);
1377 ?>
1378 <div class="vbo-bookingdet-userdetail">
1379 <span class="vbo-bookingdet-userdetail-val">&nbsp;</span>
1380 </div>
1381 <?php
1382 }
1383 }
1384 if (!empty($row['ujid'])) {
1385 $orig_user = JFactory::getUser($row['ujid']);
1386 $author_name = is_object($orig_user) && property_exists($orig_user, 'name') && !empty($orig_user->name) ? $orig_user->name : '';
1387 ?>
1388 <div class="vbo-bookingdet-userdetail">
1389 <span class="vbo-bookingdet-userdetail-val"><?php echo JText::sprintf('VBOBOOKINGCREATEDBY', $row['ujid'].(!empty($author_name) ? ' ('.$author_name.')' : '')); ?></span>
1390 </div>
1391 <?php
1392 }
1393 ?>
1394
1395 <!-- Define role to detect the supported hook -->
1396 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"userdetails","type":"field"} -->
1397
1398 <?php
1399 if (isset($bookingSidebarForms['userdetails']))
1400 {
1401 echo $bookingSidebarForms['userdetails'];
1402 }
1403 ?>
1404
1405 </div>
1406
1407 <?php
1408 // build the proper invoice SID for bc
1409 $inv_sid = $row['sid'] ?: $row['idorderota'] ?: '';
1410 if (empty($row['sid']) && is_file(implode(DIRECTORY_SEPARATOR, [VBO_SITE_PATH, 'helpers', 'invoices', 'generated', "{$row['id']}_{$row['sid']}.pdf"]))) {
1411 // use the old file name signature for OTA bookings
1412 $inv_sid = $row['sid'];
1413 }
1414
1415 // build list of invoice details (path/uri & label/button), one by default
1416 $invoice_details = [
1417 [
1418 'path' => implode(DIRECTORY_SEPARATOR, [VBO_SITE_PATH, 'helpers', 'invoices', 'generated', "{$row['id']}_{$inv_sid}.pdf"]),
1419 'uri' => VBO_SITE_URI . 'helpers/invoices/generated/' . "{$row['id']}_{$inv_sid}.pdf",
1420 'label' => JText::translate('VBOCOLORTAGRULEINVONE'),
1421 'btn' => JText::translate('VBOINVDOWNLOAD'),
1422 ]
1423 ];
1424
1425 /**
1426 * Merge the additional invoices generated by the e-invoicing drivers for this booking.
1427 *
1428 * @since 1.16.7 (J) - 1.6.7 (WP)
1429 */
1430 $invoice_details = array_merge($invoice_details, VBOEinvoicingFactory::getInstance()->getBookingExtraInvoices($row['id']));
1431
1432 /**
1433 * Trigger event to allow third-party plugins to define additional invoices or paths/urls.
1434 *
1435 * @since 1.16.7 (J) - 1.6.7 (WP)
1436 */
1437 VBOFactory::getPlatform()->getDispatcher()->trigger('onBeforeListInvoices', [$row, &$invoice_details]);
1438
1439 // check if an invoice exists
1440 $invoiced = false;
1441 foreach ((array) $invoice_details as $invoice_detail) {
1442 $invoiced = $invoiced || is_file($invoice_detail['path']);
1443 }
1444
1445 // extra booking details
1446 if (!$printreceipt && ((!empty($row['channel']) && !empty($row['idorderota'])) || strlen((string)$row['confirmnumber']) || $invoiced)) {
1447 ?>
1448 <div class="vbo-bookingdet-detcont vbo-bookingdet-detcont-labels-wrap vbo-hidein-print">
1449 <?php
1450 if (!empty($row['channel']) && !empty($row['idorderota'])) {
1451 $tiny_logo_url = '';
1452 $channelparts = explode('_', $row['channel']);
1453 if ($ch_logo = VikBooking::getVcmChannelsLogo($row['channel'], true)) {
1454 $tiny_logo_url = $ch_logo->getTinyLogoURL();
1455 }
1456 $displayOtaBid = !strcasecmp((string) $row['type'], 'Inquiry') && $row['status'] == 'standby' ? '' : $row['idorderota'];
1457 ?>
1458 <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-idorderota <?php echo strtolower(preg_replace('/[^a-z0-9]/i', '', $channelparts[0])); ?>">
1459 <span class="label label-info">
1460 <span class="vbo-bookingdet-ota-details">
1461 <?php
1462 if ($tiny_logo_url) {
1463 ?>
1464 <span class="vbo-bookingdet-ota-logo"><img src="<?php echo $tiny_logo_url; ?>" /></span>
1465 <?php
1466 }
1467 ?>
1468 <span class="vbo-bookingdet-ota-name"><?php echo $otachannel_name . ' ID'; ?></span>
1469 </span>
1470 <span class="badge<?php echo $displayOtaBid ? ' vbo-tooltip vbo-tooltip-top vbo-reservation-copy-otabid' : ''; ?>" data-tooltiptext="<?php echo JHtml::fetch('esc_attr', JText::translate('VBO_COPY')); ?>"><?php echo $displayOtaBid ? $row['idorderota'] : '-----'; ?></span>
1471 </span>
1472 <textarea class="vbo-textarea-copyable" data-copy="otabid"><?php echo htmlentities($displayOtaBid); ?></textarea>
1473 </div>
1474 <?php
1475 }
1476 if (strlen((string)$row['confirmnumber'])) {
1477 ?>
1478 <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-confirmnumber">
1479 <span class="label label-success">
1480 <span><?php echo JText::translate('VBCONFIRMNUMB'); ?></span>
1481 <span class="badge"><?php echo $row['confirmnumber']; ?></span>
1482 </span>
1483 </div>
1484 <?php
1485 }
1486
1487 /**
1488 * Check for AI automated host-to-guest reviews.
1489 *
1490 * @since 1.16.10 (J) - 1.6.10 (WP)
1491 */
1492 if (class_exists('VikChannelManager') && VikChannelManager::hostToGuestReviewSupported($row, $willbe = true)) {
1493 if (class_exists('VCMAiModelSettings') && (new VCMAiModelSettings)->isGuestReviewAutoResponderEnabled()) {
1494 // host-to-guest review will be supported and AI auto-guest-review is enabled
1495 $ai_auto_guest_review_opt = (array) VBOFactory::getConfig()->getArray('ai_auto_guest_review_opt_' . $row['id'], []);
1496 ?>
1497 <div class="vbo-bookingdet-detcont-ai-info">
1498 <p class="vbo-bookingdet-detcont-ai-info-status">
1499 <span class="vbo-bookingdet-detcont-ai-info-status-on" style="<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'display: none;' : ''; ?>"><?php VikBookingIcons::e('check-circle'); ?> <span><?php echo JText::translate('VBO_AI_AUTO_GUEST_REV_WILLRUN'); ?></span></span>
1500 <span class="vbo-bookingdet-detcont-ai-info-status-off" style="<?php echo !($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'display: none;' : ''; ?>"><?php VikBookingIcons::e('ban'); ?> <span><?php echo JText::translate('VBO_AI_AUTO_GUEST_REV_RESIGNORE'); ?></span></span>
1501 </p>
1502 <button type="button" class="btn btn-small btn-primary vbo-context-menu-btn vbo-context-menu-ai-autoreview">
1503 <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBCRONACTIONS'); ?></span>
1504 <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('sort-down'); ?></span>
1505 </button>
1506 </div>
1507
1508 <script type="text/javascript">
1509 // build context menu
1510 jQuery(function() {
1511
1512 // toggle ignore AI auto-review guest function
1513 let vbo_action_ignore_ai_autorg = (now_ignore) => {
1514 if (confirm(Joomla.JText._((now_ignore ? 'VBO_AI_AUTO_GUEST_REV_INCLUDE' : 'VBO_AI_AUTO_GUEST_REV_EXCLUDE')))) {
1515 // update the auto-review ignore status for this booking
1516 VBOCore.doAjax(
1517 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.set_ai_auto_guest_review_opt'); ?>",
1518 {
1519 bid: '<?php echo $row['id']; ?>',
1520 opt: {
1521 ignore: (now_ignore ? 0 : 1),
1522 },
1523 },
1524 (opt) => {
1525 // populate the new buttons
1526 let new_auto_review_opt = [];
1527 new_auto_review_opt.push({
1528 icon: ((opt.ignore || 0) ? '<?php echo VikBookingIcons::i('check-circle'); ?>' : '<?php echo VikBookingIcons::i('ban'); ?>'),
1529 text: Joomla.JText._((opt?.ignore ? 'VBO_AI_AUTO_GUEST_REV_INCLUDE' : 'VBO_AI_AUTO_GUEST_REV_EXCLUDE')),
1530 class: (opt?.ignore ? 'vbo-context-menu-entry-success' : 'vbo-context-menu-entry-danger'),
1531 separator: true,
1532 action: (root, config) => {
1533 // register callback
1534 vbo_action_ignore_ai_autorg(opt.ignore || 0);
1535 },
1536 });
1537
1538 // set new buttons in context menu
1539 jQuery('.vbo-context-menu-ai-autoreview').vboContextMenu('buttons', new_auto_review_opt);
1540
1541 // display the proper status label
1542 if (opt?.ignore) {
1543 jQuery('.vbo-bookingdet-detcont-ai-info-status-on').hide();
1544 jQuery('.vbo-bookingdet-detcont-ai-info-status-off').show();
1545 } else {
1546 jQuery('.vbo-bookingdet-detcont-ai-info-status-off').hide();
1547 jQuery('.vbo-bookingdet-detcont-ai-info-status-on').show();
1548 }
1549 },
1550 (error) => {
1551 // display error message
1552 alert(error.responseText);
1553 }
1554 );
1555 }
1556 };
1557
1558 // render context menu
1559 jQuery('.vbo-context-menu-ai-autoreview').vboContextMenu({
1560 placement: 'bottom-left',
1561 buttons: [
1562 {
1563 icon: '<?php echo VikBookingIcons::i(($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'check-circle' : 'ban'); ?>',
1564 text: Joomla.JText._('<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'VBO_AI_AUTO_GUEST_REV_INCLUDE' : 'VBO_AI_AUTO_GUEST_REV_EXCLUDE'; ?>'),
1565 class: '<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'vbo-context-menu-entry-success' : 'vbo-context-menu-entry-danger'; ?>',
1566 separator: true,
1567 action: (root, config) => {
1568 // register callback
1569 vbo_action_ignore_ai_autorg(<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0); ?>);
1570 },
1571 }
1572 ],
1573 });
1574
1575 });
1576 </script>
1577 <?php
1578 }
1579 }
1580
1581 if ($invoiced) {
1582 foreach ($invoice_details as $invoice_detail) {
1583 ?>
1584 <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-invoice">
1585 <span class="label label-success">
1586 <span><?php echo $invoice_detail['label'] ?? JText::translate('VBOCOLORTAGRULEINVONE'); ?></span>
1587 <span class="badge"><a href="<?php echo $invoice_detail['uri'] . (strpos($invoice_detail['uri'], '?') === false ? '?' . rand() . '=1' : ''); ?>" target="_blank"><?php VikBookingIcons::e('download'); ?> <?php echo $invoice_detail['btn'] ?? JText::translate('VBOINVDOWNLOAD'); ?></a></span>
1588 </span>
1589 </div>
1590 <?php
1591 }
1592 }
1593 if ($this->vcm_review) {
1594 ?>
1595 <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-review">
1596 <span class="label label-warning" onclick="VBOCore.handleDisplayWidgetNotification({widget_id: 'guest_reviews'}, {review_id: '<?php echo $this->vcm_review['id']; ?>'});">
1597 <a href="javascript: void(0);" style="color: #fff;"><i class="vboicn-star-full"></i> <?php echo JText::translate('VBOSEEGUESTREVIEW'); ?></a>
1598 </span>
1599 </div>
1600 <?php
1601 // check if a notification was clicked
1602 if (VikRequest::getString('notif_action', '', 'request') == 'see_guest_review') {
1603 $vcm_review_link = VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=reviews&revid=' . $this->vcm_review['id'], false);
1604 $vcm_review_id = $this->vcm_review['id'];
1605 JFactory::getDocument()->addScriptDeclaration(
1606 <<<JS
1607 jQuery(function() {
1608 setTimeout(() => {
1609 // document.location.href = '$vcm_review_link';
1610 VBOCore.handleDisplayWidgetNotification({widget_id: 'guest_reviews'}, {review_id: '$vcm_review_id'});
1611 }, 200);
1612 });
1613 JS
1614 );
1615 }
1616 }
1617 ?>
1618
1619 <!-- Define role to detect the supported hook -->
1620 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"invoice","type":"field"} -->
1621
1622 <?php
1623 if (isset($bookingSidebarForms['invoice']))
1624 {
1625 echo $bookingSidebarForms['invoice'];
1626 }
1627 ?>
1628
1629 </div>
1630 <?php
1631 }
1632 if (!$printreceipt && $row['closure'] < 1) {
1633 ?>
1634 <div class="vbo-bookingdet-detcont vbo-hidein-print">
1635 <div class="vbo-bookingdet-lblcont">
1636 <label for="custmail"><?php echo JText::translate('VBCUSTEMAIL'); ?></label>
1637 </div>
1638 <div class="vbo-bookingdet-inpwrap">
1639 <div class="vbo-bookingdet-inpcont">
1640 <input type="text" name="custmail" id="custmail" value="<?php echo $this->escape($row['custmail']); ?>" size="25" onkeyup="vboKeyupEmail(event);"/>
1641 <div class="vbo-bookingdet-btncont vbo-bookingdet-save-email" style="display: none;">
1642 <button type="button" class="btn btn-success" onclick="document.adminForm.submit();"><?php VikBookingIcons::e('save'); ?> <?php echo JText::translate('VBSAVE'); ?></button>
1643 </div>
1644 </div>
1645 <?php if (!empty($row['custmail'])) : ?>
1646 <div class="vbo-bookingdet-btncont">
1647 <button type="button" class="btn vbo-config-btn" onclick="vboDisplaySendEmail();" style="vertical-align: top;"><?php VikBookingIcons::e('envelope'); ?> <?php echo JText::translate('VBSENDEMAILACTION'); ?></button>
1648 </div>
1649 <?php endif; ?>
1650 </div>
1651
1652 <!-- Define role to detect the supported hook -->
1653 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"email","type":"field"} -->
1654
1655 <?php
1656 if (isset($bookingSidebarForms['email']))
1657 {
1658 echo $bookingSidebarForms['email'];
1659 }
1660 ?>
1661
1662 </div>
1663 <div class="vbo-bookingdet-detcont vbo-hidein-print">
1664 <div class="vbo-bookingdet-lblcont">
1665 <label for="custphone"><?php echo JText::translate('VBCUSTOMERPHONE'); ?></label>
1666 </div>
1667 <div class="vbo-bookingdet-inpwrap">
1668 <div class="vbo-bookingdet-inpcont">
1669 <?php echo $vbo_app->printPhoneInputField(array('name' => 'custphone', 'id' => 'custphone', 'value' => $this->escape($row['phone'])), array('nationalMode' => false, 'fullNumberOnBlur' => true)); ?>
1670 </div>
1671 <?php if (!empty($row['phone'])) : ?>
1672 <div class="vbo-bookingdet-btncont">
1673 <button type="button" class="btn vbo-config-btn" onclick="vboDisplaySendSMS();" style="vertical-align: top;"><?php VikBookingIcons::e('comment-dots'); ?> <?php echo JText::translate('VBSENDSMSACTION'); ?></button>
1674 </div>
1675 <?php endif; ?>
1676 </div>
1677
1678 <!-- Define role to detect the supported hook -->
1679 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"phone","type":"field"} -->
1680
1681 <?php
1682 if (isset($bookingSidebarForms['phone']))
1683 {
1684 echo $bookingSidebarForms['phone'];
1685 }
1686 ?>
1687
1688 </div>
1689
1690 <!-- Define role to detect the supported hook -->
1691 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","type":"fieldset"} -->
1692
1693 <?php
1694 foreach ($bookingSidebarForms as $legend => $form)
1695 {
1696 if (in_array($legend, ['userdetails', 'invoice', 'email', 'phone']))
1697 {
1698 // skip default forms
1699 continue;
1700 }
1701 ?>
1702 <div class="vbo-bookingdet-detcont vbo-hidein-print">
1703 <h3><?php echo JText::translate($legend); ?></h3>
1704
1705 <?php echo $form; ?>
1706 </div>
1707 <?php
1708 }
1709 ?>
1710
1711 <?php
1712 }
1713 ?>
1714 </div>
1715
1716 <?php
1717 $all_id_prices = array();
1718 $used_indexes_map = array();
1719 ?>
1720 <div class="vbo-bookingdet-summary">
1721 <div class="table-responsive">
1722 <table class="table">
1723 <?php
1724 // room stay dates in case of split stay (or modified room nights)
1725 $room_stay_dates = [];
1726 $room_stay_records = [];
1727 if ($row['split_stay']) {
1728 if ($row['status'] == 'confirmed') {
1729 $room_stay_dates = $av_helper->loadSplitStayBusyRecords($row['id']);
1730 } else {
1731 $room_stay_dates = VBOFactory::getConfig()->getArray('split_stay_' . $row['id'], []);
1732 }
1733 } elseif (!$row['split_stay'] && $row['roomsnum'] > 1 && $row['days'] > 1 && $row['status'] == 'confirmed') {
1734 // load the occupied stay dates for each room in case they were modified
1735 $room_stay_records = $av_helper->loadSplitStayBusyRecords($row['id']);
1736 }
1737
1738 // parse all rooms booked
1739 foreach ($rooms as $ind => $or) {
1740 $num = $ind + 1;
1741 $room_icon = $row['split_stay'] && $ind > 0 ? 'random' : 'bed';
1742 $room_stay_nights = $row['days'];
1743 ?>
1744 <tr class="vbo-bookingdet-summary-room">
1745 <td class="vbo-bookingdet-summary-room-firstcell">
1746 <div class="vbo-bookingdet-summary-room-wrap">
1747 <div class="vbo-bookingdet-summary-roomnum"><?php VikBookingIcons::e($room_icon); ?> <?php echo JText::translate('VBEDITORDERTHREE').' '.$num; ?></div>
1748 <?php
1749 // Room Specific Unit
1750 if ((!$row['closure'] || ($row['closure'] && count($rooms) === 1) && !empty($or['roomindex'])) && $row['status'] == "confirmed" && !empty($or['params'])) {
1751 $room_params = json_decode($or['params'], true);
1752 $arr_features = array();
1753 $unavailable_indexes = VikBooking::getRoomUnitNumsUnavailable($row, $or['idroom']);
1754 if (is_array($room_params) && array_key_exists('features', $room_params) && !empty($room_params['features'])) {
1755 foreach ($room_params['features'] as $rind => $rfeatures) {
1756 if (in_array($rind, $unavailable_indexes) || (isset($used_indexes_map[$or['idroom']]) && in_array($rind, $used_indexes_map[$or['idroom']]))) {
1757 continue;
1758 }
1759 foreach ($rfeatures as $fname => $fval) {
1760 if (strlen($fval)) {
1761 $arr_features[$rind] = '#'.$rind.' - '.JText::translate($fname).': '.$fval;
1762 break;
1763 }
1764 }
1765 }
1766 }
1767 if ($arr_features) {
1768 // $or['id'] equals to the ID of each matching record in _ordersrooms
1769 ?>
1770 <div class="vbo-bookingdet-summary-roomnum-chunit">
1771 <?php echo !$printreceipt ? $vbo_app->getNiceSelect($arr_features, $or['roomindex'], 'roomindex['.$or['id'].']', JText::translate('VBOFEATASSIGNUNIT'), JText::translate('VBOFEATASSIGNUNITEMPTY'), '', 'document.adminForm.submit();', $or['id']) : (!empty($or['roomindex']) && isset($arr_features[$or['roomindex']]) ? $arr_features[$or['roomindex']] : ''); ?>
1772 </div>
1773 <?php
1774 if (!empty($or['idroom']) && !empty($or['roomindex'])) {
1775 if (!array_key_exists($or['idroom'], $used_indexes_map)) {
1776 $used_indexes_map[$or['idroom']] = array();
1777 }
1778 $used_indexes_map[$or['idroom']][] = $or['roomindex'];
1779 }
1780 }
1781 }
1782 //
1783 ?>
1784 </div>
1785 <div class="vbo-bookingdet-summary-roomguests">
1786 <?php VikBookingIcons::e('male'); ?>
1787 <div class="vbo-bookingdet-summary-roomadults">
1788 <span><?php echo JText::translate('VBEDITORDERADULTS'); ?>:</span> <?php echo $arrpeople[$num]['adults']; ?>
1789 </div>
1790 <?php
1791 if ($arrpeople[$num]['children'] > 0) {
1792 $age_str = '';
1793 if (!empty($arrpeople[$num]['children_age'])) {
1794 $json_child = json_decode($arrpeople[$num]['children_age'], true);
1795 if (is_array($json_child) && isset($json_child['age']) && is_array($json_child['age']) && $json_child['age']) {
1796 $age_str = ' '.JText::sprintf('VBORDERCHILDAGES', implode(', ', $json_child['age']));
1797 }
1798 }
1799 ?>
1800 <div class="vbo-bookingdet-summary-roomchildren">
1801 <span><?php echo JText::translate('VBEDITORDERCHILDREN'); ?>:</span> <?php echo $arrpeople[$num]['children'].$age_str; ?>
1802 </div>
1803 <?php
1804 }
1805 if ($arrpeople[$num]['pets'] > 0) {
1806 ?>
1807 <div class="vbo-bookingdet-summary-roompets">
1808 <span><?php VikBookingIcons::e('dog'); ?> <?php echo JText::translate('VBO_PETS'); ?>:</span> <?php echo $arrpeople[$num]['pets']; ?>
1809 </div>
1810 <?php
1811 }
1812 ?>
1813 </div>
1814 <?php
1815 if (!empty($arrpeople[$num]['t_first_name'])) {
1816 ?>
1817 <div class="vbo-bookingdet-summary-guestname">
1818 <span><?php echo $arrpeople[$num]['t_first_name'].' '.$arrpeople[$num]['t_last_name']; ?></span>
1819 </div>
1820 <?php
1821 }
1822 ?>
1823 </td>
1824 <td>
1825 <div class="vbo-bookingdet-summary-roomname"><?php echo $or['name']; ?></div>
1826 <div class="vbo-bookingdet-summary-roomrate">
1827 <?php
1828 $active_rplan_id = 0;
1829 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
1830 if (!empty($or['pkg_name'])) {
1831 //package
1832 echo $or['pkg_name'];
1833 } else {
1834 //custom cost can have an OTA Rate Plan name
1835 if (!empty($or['otarplan'])) {
1836 echo ucwords($or['otarplan']);
1837 } else {
1838 echo JText::translate('VBOROOMCUSTRATEPLAN');
1839 }
1840 }
1841 } elseif (!empty($tars[$num]) && !empty($tars[$num][0]['idprice'])) {
1842 $active_rplan_id = $tars[$num][0]['idprice'];
1843 $all_id_prices[] = $tars[$num][0]['idprice'];
1844 echo VikBooking::getPriceName($tars[$num][0]['idprice']);
1845 if (!empty($tars[$num][0]['attrdata'])) {
1846 ?>
1847 <div>
1848 <?php echo VikBooking::getPriceAttr($tars[$num][0]['idprice']).": ".$tars[$num][0]['attrdata']; ?>
1849 </div>
1850 <?php
1851 }
1852 } elseif (!empty($or['otarplan'])) {
1853 echo ucwords($or['otarplan']);
1854 } elseif ($row['closure'] < 1) {
1855 echo JText::translate('VBOROOMNORATE');
1856 }
1857 ?>
1858 </div>
1859 <?php
1860 // meals included in the room rate
1861 if (!empty($or['meals'])) {
1862 // display included meals defined at room-reservation record
1863 $included_meals = VBOMealplanManager::getInstance()->roomRateIncludedMeals($or);
1864 } else {
1865 // fetch default included meals in the selected rate plan
1866 $included_meals = $active_rplan_id ? VBOMealplanManager::getInstance()->ratePlanIncludedMeals($active_rplan_id) : [];
1867 }
1868 if (!$included_meals && empty($or['meals']) && !empty($row['idorderota']) && !empty($row['channel']) && !empty($row['custdata'])) {
1869 // attempt to fetch the included meal plans from the raw customer data or OTA reservation and room
1870 $included_meals = VBOMealplanManager::getInstance()->otaDataIncludedMeals($row, $or);
1871 }
1872 if ($included_meals) {
1873 ?>
1874 <div class="vbo-bookingdet-summary-roomrate vbo-bookingdet-summary-roommeals vbo-wider-badges-wrap">
1875 <?php
1876 foreach ($included_meals as $included_meal) {
1877 ?>
1878 <span class="badge badge-info"><?php echo $included_meal; ?></span>
1879 <?php
1880 }
1881 ?>
1882 </div>
1883 <?php
1884 }
1885
1886 if ($row['split_stay'] && $room_stay_dates && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) {
1887 // print split stay information for this room
1888 $room_stay_checkin = !empty($room_stay_dates[$ind]['checkin_ts']) ? $room_stay_dates[$ind]['checkin_ts'] : $room_stay_dates[$ind]['checkin'];
1889 $room_stay_checkout = !empty($room_stay_dates[$ind]['checkout_ts']) ? $room_stay_dates[$ind]['checkout_ts'] : $room_stay_dates[$ind]['checkout'];
1890 $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout);
1891 ?>
1892 <div class="vbo-cal-splitstay-details vbo-bookdet-splitstay-details">
1893 <div class="vbo-cal-splitstay-dates">
1894 <span class="vbo-cal-splitstay-room-nights"><?php VikBookingIcons::e('moon'); ?> <?php echo $room_stay_nights . ' ' . ($room_stay_nights > 1 ? JText::translate('VBDAYS') : JText::translate('VBDAY')); ?></span>
1895 <span class="vbo-cal-splitstay-dates-in" title="<?php echo date('H:i', $room_stay_checkin); ?>"><?php VikBookingIcons::e('plane-arrival'); ?> <?php echo date(str_replace("/", $datesep, $df), $room_stay_checkin); ?></span>
1896 <span class="vbo-cal-splitstay-dates-out" title="<?php echo date('H:i', $room_stay_checkout); ?>"><?php VikBookingIcons::e('plane-departure'); ?> <?php echo date(str_replace("/", $datesep, $df), $room_stay_checkout); ?></span>
1897 </div>
1898 </div>
1899 <?php
1900 } elseif (!$row['split_stay'] && $room_stay_records && isset($room_stay_records[$ind]) && $room_stay_records[$ind]['idroom'] == $or['idroom']) {
1901 // print modified stay dates information for this room
1902 $room_stay_checkin = $room_stay_records[$ind]['checkin'];
1903 $room_stay_checkout = $room_stay_records[$ind]['checkout'];
1904 $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout);
1905 if ($room_stay_checkin != $row['checkin'] || $room_stay_checkout != $row['checkout']) {
1906 ?>
1907 <div class="vbo-cal-splitstay-details vbo-bookdet-splitstay-details vbo-bookdet-roomdatesmod-details">
1908 <div class="vbo-cal-splitstay-dates">
1909 <span class="vbo-cal-splitstay-room-nights"><?php VikBookingIcons::e('moon'); ?> <?php echo $room_stay_nights . ' ' . ($room_stay_nights > 1 ? JText::translate('VBDAYS') : JText::translate('VBDAY')); ?></span>
1910 <span class="vbo-cal-splitstay-dates-in" title="<?php echo date('H:i', $room_stay_checkin); ?>"><?php VikBookingIcons::e('plane-arrival'); ?> <?php echo date(str_replace("/", $datesep, $df), $room_stay_checkin); ?></span>
1911 <span class="vbo-cal-splitstay-dates-out" title="<?php echo date('H:i', $room_stay_checkout); ?>"><?php VikBookingIcons::e('plane-departure'); ?> <?php echo date(str_replace("/", $datesep, $df), $room_stay_checkout); ?></span>
1912 </div>
1913 </div>
1914 <?php
1915 }
1916 }
1917 ?>
1918 </td>
1919 <td>
1920 <div class="vbo-bookingdet-summary-price">
1921 <?php
1922 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
1923 echo $currencyname.' '.VikBooking::numberFormat($or['cust_cost']);
1924 } elseif (!empty($tars[$num]) && !empty($tars[$num][0]['idprice'])) {
1925 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num][0]['cost'];
1926 echo $currencyname.' '.VikBooking::numberFormat(($after_tax ? VikBooking::sayCostPlusIva($display_rate, $tars[$num][0]['idprice']) : $display_rate));
1927 }
1928 ?>
1929 </div>
1930 </td>
1931 </tr>
1932 <?php
1933 //Options
1934 if (!empty($or['optionals'])) {
1935 $stepo = explode(";", $or['optionals']);
1936 $counter = 0;
1937 foreach ($stepo as $roptkey => $oo) {
1938 if (empty($oo)) {
1939 continue;
1940 }
1941 $stept = explode(":", $oo);
1942 $q = "SELECT * FROM `#__vikbooking_optionals` WHERE `id`=".(int)$stept[0].";";
1943 $dbo->setQuery($q);
1944 $actopt = $dbo->loadAssocList();
1945 if (!$actopt) {
1946 continue;
1947 }
1948
1949 // option params
1950 $opt_params = !empty($actopt[0]['oparams']) ? json_decode($actopt[0]['oparams'], true) : [];
1951 $opt_params = is_array($opt_params) ? $opt_params : [];
1952 if ($opt_params['damagedep'] ?? 0) {
1953 // turn flag on
1954 $booking_has_damage_dep = 1;
1955 }
1956
1957 $counter++;
1958 $chvar = '';
1959 if (!empty($actopt[0]['ageintervals']) && $or['children'] > 0 && strstr($stept[1], '-') != false) {
1960 $optagenames = VikBooking::getOptionIntervalsAges($actopt[0]['ageintervals']);
1961 $optagepcent = VikBooking::getOptionIntervalsPercentage($actopt[0]['ageintervals']);
1962 $optageovrct = VikBooking::getOptionIntervalChildOverrides($actopt[0], $or['adults'], $or['children']);
1963 $child_num = VikBooking::getRoomOptionChildNumber($or['optionals'], $actopt[0]['id'], $roptkey, $or['children']);
1964 $optagecosts = VikBooking::getOptionIntervalsCosts(isset($optageovrct['ageintervals_child' . ($child_num + 1)]) ? $optageovrct['ageintervals_child' . ($child_num + 1)] : $actopt[0]['ageintervals']);
1965 $agestept = explode('-', $stept[1]);
1966 $stept[1] = $agestept[0];
1967 $chvar = $agestept[1];
1968 if (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 1) {
1969 //percentage value of the adults tariff
1970 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
1971 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
1972 } else {
1973 $display_rate = !empty($or['room_cost']) ? $or['room_cost'] : $tars[$num][0]['cost'];
1974 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
1975 }
1976 } elseif (array_key_exists(($chvar - 1), $optagepcent) && $optagepcent[($chvar - 1)] == 2) {
1977 //VBO 1.10 - percentage value of room base cost
1978 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
1979 $optagecosts[($chvar - 1)] = $or['cust_cost'] * $optagecosts[($chvar - 1)] / 100;
1980 } else {
1981 $display_rate = isset($tars[$num][0]['room_base_cost']) ? $tars[$num][0]['room_base_cost'] : (!empty($or['room_cost']) ? $or['room_cost'] : $tars[$num][0]['cost']);
1982 $optagecosts[($chvar - 1)] = $display_rate * $optagecosts[($chvar - 1)] / 100;
1983 }
1984 }
1985 if (!isset($optagenames[($chvar - 1)])) {
1986 $optagenames[($chvar - 1)] = '';
1987 }
1988 if (!isset($optagecosts[($chvar - 1)])) {
1989 $optagecosts[($chvar - 1)] = 0;
1990 }
1991 $actopt[0]['chageintv'] = $chvar;
1992 $actopt[0]['name'] .= ' ('.$optagenames[($chvar - 1)].')';
1993 $realcost = (intval($actopt[0]['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $room_stay_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1]));
1994 } elseif (is_numeric($stept[1])) {
1995 // VBO 1.11 - options percentage cost of the room total fee
1996 if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) {
1997 $deftar_basecosts = $or['cust_cost'];
1998 } else {
1999 $use_def_tar = isset($tars[$num]) && isset($tars[$num][0]) ? $tars[$num][0]['cost'] : 0;
2000 $deftar_basecosts = !empty($or['room_cost']) ? $or['room_cost'] : $use_def_tar;
2001 }
2002 $actopt[0]['cost'] = (int)$actopt[0]['pcentroom'] ? ($deftar_basecosts * $actopt[0]['cost'] / 100) : $actopt[0]['cost'];
2003 //
2004 $realcost = (intval($actopt[0]['perday']) == 1 ? ($actopt[0]['cost'] * $room_stay_nights * $stept[1]) : ($actopt[0]['cost'] * $stept[1]));
2005 } else {
2006 $realcost = 0;
2007 }
2008 if ($actopt[0]['maxprice'] > 0 && $realcost > $actopt[0]['maxprice']) {
2009 $realcost = $actopt[0]['maxprice'];
2010 if (intval($actopt[0]['hmany']) == 1 && intval($stept[1]) > 1) {
2011 $realcost = $actopt[0]['maxprice'] * $stept[1];
2012 }
2013 }
2014 $realcost = $actopt[0]['perperson'] == 1 ? ($realcost * $arrpeople[$num]['adults']) : $realcost;
2015
2016 /**
2017 * Trigger event to allow third party plugins to apply a custom calculation for the option/extra fee or tax.
2018 *
2019 * @since 1.17.7 (J) - 1.7.7 (WP)
2020 */
2021 $custom_calculation = VBOFactory::getPlatform()->getDispatcher()->filter('onCalculateBookingOptionFeeCost', [$realcost, &$actopt[0], $row, $or]);
2022 if ($custom_calculation) {
2023 $realcost = (float) $custom_calculation[0];
2024 }
2025
2026 $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt[0]['idiva']);
2027 ?>
2028 <tr class="vbo-bookingdet-summary-options">
2029 <td class="vbo-bookingdet-summary-options-title"><?php echo $counter == 1 ? JText::translate('VBEDITORDEREIGHT') : '&nbsp;'; ?></td>
2030 <td>
2031 <span class="vbo-bookingdet-summary-lbl"><?php echo ($stept[1] > 1 ? $stept[1]." " : "").$actopt[0]['name']; ?></span>
2032 </td>
2033 <td>
2034 <span class="vbo-bookingdet-summary-cost"><?php echo $currencyname." ".VikBooking::numberFormat(($after_tax ? $tmpopr : $realcost)); ?></span>
2035 </td>
2036 </tr>
2037 <?php
2038 }
2039 }
2040 //Custom extra costs
2041 if (!empty($or['extracosts'])) {
2042 $counter = 0;
2043 $cur_extra_costs = json_decode($or['extracosts'], true);
2044 foreach ($cur_extra_costs as $eck => $ecv) {
2045 $counter++;
2046 $ecv['idtax'] = isset($ecv['idtax']) ? $ecv['idtax'] : 0;
2047 ?>
2048 <tr class="vbo-bookingdet-summary-custcosts">
2049 <td class="vbo-bookingdet-summary-custcosts-title"><?php echo $counter == 1 ? JText::translate('VBPEDITBUSYEXTRACOSTS') : '&nbsp;'; ?></td>
2050 <td>
2051 <?php
2052 if (!empty($ecv['type'])) {
2053 ?>
2054 <span class="vbo-tooltip vbo-tooltip-top" data-tooltiptext="<?php echo JHtml::fetch('esc_attr', JText::translate('VBPSHOWSEASONSTHREE') . ': ' . $ecv['type']); ?>">
2055 <span class="vbo-bookingdet-summary-lbl"><?php echo $ecv['name']; ?></span>
2056 </span>
2057 <?php
2058 } else {
2059 ?>
2060 <span class="vbo-bookingdet-summary-lbl"><?php echo $ecv['name']; ?></span>
2061 <?php
2062 }
2063 ?>
2064 </td>
2065 <td>
2066 <span class="vbo-bookingdet-summary-cost"><?php echo $currencyname." ".VikBooking::numberFormat(($after_tax ? VikBooking::sayOptionalsPlusIva($ecv['cost'], $ecv['idtax']) : $ecv['cost'])); ?></span>
2067 </td>
2068 </tr>
2069 <?php
2070 }
2071 }
2072 }
2073 //vikbooking 1.1 coupon
2074 if (strlen((string)$row['coupon']) > 0) {
2075 $expcoupon = explode(";", $row['coupon']);
2076 ?>
2077 <tr class="vbo-bookingdet-summary-coupon">
2078 <td><?php echo JText::translate('VBCOUPON'); ?></td>
2079 <td>
2080 <span class="vbo-bookingdet-summary-lbl"><?php echo $expcoupon[2]; ?></span>
2081 </td>
2082 <td>
2083 <span class="vbo-bookingdet-summary-cost">- <?php echo $currencyname; ?> <?php echo VikBooking::numberFormat($expcoupon[1]); ?></span>
2084 </td>
2085 </tr>
2086 <?php
2087 }
2088 if ($row['refund'] > 0) {
2089 ?>
2090 <tr class="vbo-bookingdet-summary-totpaid vbo-bookingdet-summary-totrefunded">
2091 <td>
2092 <strong><?php echo JText::translate('VBOBOOKHISTORYTRF'); ?></strong>
2093 </td>
2094 <td>
2095 <span class="vbo-amount-refunded-lbl"><?php echo JText::translate('VBO_AMOUNT_REFUNDED'); ?></span>
2096 </td>
2097 <td>
2098 <div id="vbo-amountrefunded-cont">
2099 <span id="vbo-amountrefunded-current"><?php echo $currencyname.' '.VikBooking::numberFormat($row['refund']); ?></span>
2100 <span id="vbo-amountrefunded-edit" style="margin-left: 5px; cursor: pointer;"><?php VikBookingIcons::e('edit'); ?></span>
2101 </div>
2102 <div id="vbo-amountrefunded-modcont" style="display: none;">
2103 <span id="vbo-amountrefunded-cancedit" style="margin-right: 5px; cursor: pointer;"><?php VikBookingIcons::e('times'); ?></span>
2104 <span id="vbo-amountrefunded-new"><input type="number" step="any" name="newamountrefunded" value="" min="0" style="margin: 0;" placeholder="<?php echo $row['refund']; ?>" disabled /></span>
2105 <span id="vbo-amountrefunded-save"><button type="submit" class="btn btn-success"><?php echo JText::translate('VBAPPLYDISCOUNTSAVE'); ?></button></span>
2106 </div>
2107 </td>
2108 </tr>
2109 <?php
2110 }
2111 //Reservation Total
2112 //Taxes Breakdown (only if tot_taxes is greater than 0)
2113 $tax_breakdown = array();
2114 $base_aliq = 0;
2115 if ($all_id_prices && $row['tot_taxes'] > 0) {
2116 //only last type of price assuming that the tax breakdown is equivalent in case of different rates
2117 $q = "SELECT `p`.`id`,`p`.`name`,`p`.`idiva`,`t`.`aliq`,`t`.`breakdown` FROM `#__vikbooking_prices` AS `p` LEFT JOIN `#__vikbooking_iva` `t` ON `p`.`idiva`=`t`.`id` WHERE `p`.`id`=".intval(array_pop($all_id_prices))." LIMIT 1;";
2118 $dbo->setQuery($q);
2119 $breakdown_info = $dbo->loadAssoc();
2120 if ($breakdown_info) {
2121 if (!empty($breakdown_info['breakdown']) && !empty($breakdown_info['aliq'])) {
2122 $tax_breakdown = json_decode($breakdown_info['breakdown'], true);
2123 $tax_breakdown = is_array($tax_breakdown) && $tax_breakdown ? $tax_breakdown : array();
2124 $base_aliq = $breakdown_info['aliq'];
2125 }
2126 }
2127 }
2128 //
2129 if ($printreceipt && $row['tot_taxes'] > 0) {
2130 // only when printing the receipt we display an additional row for the total amount of tax
2131 ?>
2132 <tr class="vbo-bookingdet-summary-total vbo-bookingdet-summary-totaltax">
2133 <td>
2134
2135 </td>
2136 <td>
2137 <span class="vbo-bookingdet-summary-lbl"><?php echo JText::translate('VBTOTALVAT'); ?></span>
2138 </td>
2139 <td>
2140 <span class="vbo-bookingdet-summary-cost"><?php echo $currencyname; ?> <?php echo VikBooking::numberFormat($row['tot_taxes']); ?></span>
2141 </td>
2142 </tr>
2143 <?php
2144 }
2145 ?>
2146 <tr class="vbo-bookingdet-summary-total">
2147 <td>
2148 <?php
2149 if (!$printreceipt) {
2150 ?>
2151 <span class="vbapplydiscsp" onclick="toggleDiscount(this);">
2152 <i class="<?php echo VikBookingIcons::i('chevron-down'); ?>" title="<?php echo htmlspecialchars(JText::translate('VBAPPLYDISCOUNT')); ?>"></i>
2153 </span>
2154 <?php
2155 }
2156 ?>
2157 </td>
2158 <td>
2159 <span class="vbo-bookingdet-summary-lbl"><?php echo JText::translate('VBEDITORDERNINE'); ?></span>
2160
2161 <div class="vbdiscenter" id="vbdiscenter" style="display: none;">
2162 <div class="vbdiscenter-entry">
2163 <span class="vbdiscenter-label"><?php echo JText::translate('VBTOTALVAT'); ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <input type="number" step="any" name="tot_taxes" value="<?php echo $row['tot_taxes']; ?>" size="4"/></span>
2164 </div>
2165 <?php
2166 if ($tax_breakdown) {
2167 foreach ($tax_breakdown as $tbkk => $tbkv) {
2168 $tax_break_cost = $row['tot_taxes'] * floatval($tbkv['aliq']) / $base_aliq;
2169 ?>
2170 <div class="vbdiscenter-entry vbdiscenter-entry-breakdown">
2171 <span class="vbdiscenter-label"><?php echo $tbkv['name']; ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <?php echo VikBooking::numberFormat($tax_break_cost); ?></span>
2172 </div>
2173 <?php
2174 }
2175 }
2176 ?>
2177 <div class="vbdiscenter-entry">
2178 <span class="vbdiscenter-label"><?php echo JText::translate('VBTOTALCITYTAX'); ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <input type="number" step="any" name="tot_city_taxes" value="<?php echo $row['tot_city_taxes']; ?>" size="4"/></span>
2179 </div>
2180 <div class="vbdiscenter-entry">
2181 <span class="vbdiscenter-label"><?php echo JText::translate('VBTOTALFEES'); ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <input type="number" step="any" name="tot_fees" value="<?php echo $row['tot_fees']; ?>" size="4"/></span>
2182 </div>
2183 <div class="vbdiscenter-entry">
2184 <span class="vbdiscenter-label hasTooltip"<?php echo !empty($otachannel_name) ? ' title="'.$otachannel_name.'"' : ''; ?>><?php echo JText::translate('VBTOTALCOMMISSIONS'); ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <input type="number" step="any" name="cmms" value="<?php echo $row['cmms']; ?>" size="4"/></span>
2185 </div>
2186 <?php
2187 if ($booking_has_damage_dep) {
2188 // allow to overwrite (or see) the amount of damage deposit
2189 ?>
2190 <div class="vbdiscenter-entry">
2191 <span class="vbdiscenter-label"><?php echo JText::translate('VBO_DAMAGE_DEPOSIT'); ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <input type="number" step="any" name="tot_damage_dep" value="<?php echo $row['tot_damage_dep']; ?>" min="0" size="4"/></span>
2192 </div>
2193 <?php
2194 }
2195 ?>
2196 <div class="vbdiscenter-entry">
2197 <span class="vbdiscenter-label"><?php echo JText::translate('VBAPPLYDISCOUNT'); ?>:</span><span class="vbdiscenter-value"><?php echo $currencyname; ?> <input type="number" step="any" name="admindisc" value="<?php echo isset($expcoupon) ? (float)$expcoupon[1] : ''; ?>" size="4"/></span>
2198 </div>
2199 <div class="vbdiscenter-entrycentered">
2200 <button type="submit" class="btn btn-success"><?php echo JText::translate('VBAPPLYDISCOUNTSAVE'); ?></button>
2201 </div>
2202 </div>
2203 </td>
2204 <td>
2205 <span class="vbo-bookingdet-summary-cost"><?php echo (!empty($otacurrency) && $otacurrency != $currencyname ? '('.$otacurrency.') ' . $currencyname : $currencyname); ?> <?php echo VikBooking::numberFormat($row['total']); ?></span>
2206 <?php
2207 /**
2208 * Display the information about the expected payout, if available and eligible.
2209 *
2210 * @since 1.18.4 (J) - 1.8.4 (WP)
2211 */
2212 if ($row['status'] == 'confirmed' && !empty($row['channel']) && !empty($row['idorderota']) && $row['checkout'] >= $current_ts && !empty($ota_type_data['expected_payout'])) {
2213 ?>
2214 <div class="vbo-bookingdet-exp-payout">
2215 <span class="vbo-bookingdet-exp-payout-lbl"><?php echo JText::translate('VBO_EXPECTED_PAYOUT'); ?></span>
2216 <span class="vbo-bookingdet-exp-payout-txt"><?php
2217 echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($ota_type_data['expected_payout']), (!empty($otacurrency) && $otacurrency != $currencyname ? $otacurrency : $currencysymb));
2218 ?></span>
2219 </div>
2220 <?php
2221 }
2222 ?>
2223 </td>
2224 </tr>
2225 <?php
2226 if ($row['total'] > 0 && !$row['closure']) {
2227 $has_paid = ($row['totpaid'] > 0);
2228 $diff_to_pay = $has_paid ? ($row['total'] - $row['totpaid']) : 0;
2229 if ($has_paid || $row['status'] != 'standby') {
2230 ?>
2231 <tr class="vbo-bookingdet-summary-totpaid">
2232 <td>&nbsp;</td>
2233 <td><?php echo JText::translate('VBAMOUNTPAID'); ?></td>
2234 <td>
2235 <div id="vbo-amountpaid-cont">
2236 <span id="vbo-amountpaid-current"><?php echo $has_paid ? ($currencyname . ' ' . VikBooking::numberFormat($row['totpaid'])) : ''; ?></span>
2237 <span id="vbo-amountpaid-edit" style="margin-left: 5px; cursor: pointer;"><?php VikBookingIcons::e('edit'); ?></span>
2238 </div>
2239 <div id="vbo-amountpaid-modcont" style="display: none;">
2240 <span id="vbo-amountpaid-cancedit" style="margin-right: 5px; cursor: pointer;"><?php VikBookingIcons::e('times'); ?></span>
2241 <span id="vbo-amountpaid-new"><input type="number" step="any" name="newamountpaid" value="" min="0" style="margin: 0;" placeholder="<?php echo $has_paid ? $row['totpaid'] : ''; ?>" disabled /></span>
2242 <?php
2243 if ($payments) {
2244 ?>
2245 <span id="vbo-amountpaid-paymeth" style="margin: 0 5px; max-width: 160px;">
2246 <select name="newamountpaymeth" style="margin: 0;">
2247 <option value=""><?php echo JText::translate('VBPAYMENTMETHOD'); ?></option>
2248 <?php
2249 foreach ($payments as $pay) {
2250 ?>
2251 <option value="<?php echo JHtml::fetch('esc_attr', $pay['id'] . '_' . $pay['name']); ?>"><?php echo $pay['name']; ?></option>
2252 <?php
2253 }
2254 ?>
2255 </select>
2256 </span>
2257 <?php
2258 }
2259 ?>
2260 <span id="vbo-amountpaid-save"><button type="submit" class="btn btn-success"><?php echo JText::translate('VBAPPLYDISCOUNTSAVE'); ?></button></span>
2261 </div>
2262 </td>
2263 </tr>
2264 <?php
2265 }
2266 if ($diff_to_pay > 1 && $row['status'] != 'cancelled') {
2267 ?>
2268 <tr class="vbo-bookingdet-summary-totpaid vbo-bookingdet-summary-totremaining">
2269 <td>&nbsp;</td>
2270 <td>
2271 <div><?php echo JText::translate('VBTOTALREMAINING'); ?></div>
2272 <?php
2273 // enable second payment
2274 if (!$printreceipt && $row['status'] == 'confirmed' && !($row['paymcount'] > 0) && VikBooking::multiplePayments() && is_array($payment) && !empty($payment['id'])) {
2275 ?>
2276 <div style="margin-top: 5px;">
2277 <a href="index.php?option=com_vikbooking&amp;task=editorder&amp;makepay=1&amp;cid[]=<?php echo $row['id']; ?>" class="vbo-makepayable-link"><?php VikBookingIcons::e('credit-card'); ?> <?php echo JText::translate('VBMAKEORDERPAYABLE'); ?></a>
2278 </div>
2279 <?php
2280 }
2281 ?>
2282 </td>
2283 <td><?php echo $currencyname . ' ' . VikBooking::numberFormat($diff_to_pay); ?></td>
2284 </tr>
2285 <?php
2286 }
2287 }
2288 if (!$printreceipt && $row['status'] == 'confirmed' && VikBooking::multiplePayments() && is_array($payment) && !empty($payment['id']) && $row['checkout'] > strtotime('-10 days')) {
2289 /**
2290 * The amount payable can be modified by the admin.
2291 *
2292 * @since 1.14 (J) - 1.4.0 (WP)
2293 */
2294 ?>
2295 <tr class="vbo-bookingdet-summary-totpaid vbo-bookingdet-summary-totpayable">
2296 <td>&nbsp;</td>
2297 <td>
2298 <span class="vbo-amount-payable-lbl<?php echo $row['payable'] > 0 ? ' vbo-amount-payable-lbl-requested' : ''; ?>"><?php echo $row['payable'] > 0 ? JText::translate('VBO_AMOUNT_PAYABLE') : JText::translate('VBO_AMOUNT_PAYABLE_RQ'); ?></span>
2299 </td>
2300 <td>
2301 <div id="vbo-amountpayable-cont">
2302 <?php
2303 if ($row['payable'] > 0) {
2304 ?>
2305 <span id="vbo-amountpayable-current"><?php echo $currencyname . ' ' . VikBooking::numberFormat($row['payable']); ?></span>
2306 <?php
2307 }
2308 ?>
2309 <span id="vbo-amountpayable-edit" style="margin-left: 5px; cursor: pointer;"><?php VikBookingIcons::e('edit'); ?></span>
2310 </div>
2311 <div id="vbo-amountpayable-modcont" style="display: none;">
2312 <span id="vbo-amountpayable-cancedit" style="margin-right: 5px; cursor: pointer;"><?php VikBookingIcons::e('times'); ?></span>
2313 <span id="vbo-amountpayable-new"><input type="number" step="any" name="newamountpayable" value="" min="0" style="margin: 0;" placeholder="<?php echo $row['payable']; ?>" disabled /></span>
2314 <span id="vbo-amountpayable-save"><button type="submit" class="btn btn-success"><?php echo JText::translate('VBAPPLYDISCOUNTSAVE'); ?></button></span>
2315 </div>
2316 </td>
2317 </tr>
2318 <?php
2319 }
2320
2321 /**
2322 * Cancellation fee for cancelled bookings after the deadline.
2323 *
2324 * @since 1.16.0 (J) - 1.6.0 (WP)
2325 */
2326 if ($row['status'] == 'cancelled' && !$row['closure'] && $row['total'] > 0) {
2327 ?>
2328 <tr class="vbo-bookingdet-summary-cancfee">
2329 <td>&nbsp;</td>
2330 <td><?php echo JText::translate('VBO_CANC_FEE'); ?></td>
2331 <td>
2332 <div id="vbo-cancfee-cont">
2333 <span id="vbo-cancfee-current"><?php echo $currencyname.' '.VikBooking::numberFormat($row['canc_fee']); ?></span>
2334 <span id="vbo-cancfee-edit" style="margin-left: 5px; cursor: pointer;"><?php VikBookingIcons::e('edit'); ?></span>
2335 </div>
2336 <div id="vbo-cancfee-modcont" style="display: none;">
2337 <span id="vbo-cancfee-cancedit" style="margin-right: 5px; cursor: pointer;"><?php VikBookingIcons::e('times'); ?></span>
2338 <span id="vbo-cancfee-new"><input type="number" step="any" name="newcancfee" value="" min="0" style="margin: 0;" placeholder="<?php echo $row['canc_fee']; ?>" disabled /></span>
2339 <span id="vbo-cancfee-save"><button type="submit" class="btn btn-success"><?php echo JText::translate('VBAPPLYDISCOUNTSAVE'); ?></button></span>
2340 </div>
2341 </td>
2342 </tr>
2343 <?php
2344 }
2345 ?>
2346 </table>
2347 </div>
2348
2349 <!-- Define role to detect the supported hook -->
2350 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorder","type":"fieldset"} -->
2351
2352 <?php
2353 foreach ($bookingPanelForms as $legend => $form)
2354 {
2355 if (in_array($legend, ['buttons']))
2356 {
2357 // skip default forms
2358 continue;
2359 }
2360 ?>
2361 <div class="table-responsive">
2362 <h3><?php echo JText::translate($legend); ?></h3>
2363
2364 <?php echo $form; ?>
2365 </div>
2366 <?php
2367 }
2368 ?>
2369
2370 </div>
2371 </div>
2372 <?php
2373 if ($printreceipt) {
2374 $receipt_notes = VikBooking::getReceiptNotes();
2375 ?>
2376 <div class="vbo-receipt-notes-container">
2377 <div class="vbo-receipt-notes-inner">
2378 <div class="vbo-receipt-notes-val vbo-showin-print" id="vbo-receipt-notes-val"><?php echo $receipt_notes; ?></div>
2379 <div class="vbo-receipt-notes-tarea vbo-hidein-print">
2380 <textarea id="vbo-receipt-notes" placeholder="<?php echo JText::translate('VBORECEIPTNOTESDEF'); ?>"><?php echo htmlspecialchars($receipt_notes); ?></textarea>
2381 </div>
2382 </div>
2383 </div>
2384 <?php
2385 }
2386 ?>
2387 </div>
2388
2389 <div class="vbo-bookingdet-tab-cont" id="vbo-tab-admin" style="display: none;">
2390 <div class="vbo-bookingdet-innercontainer">
2391 <div class="vbo-bookingdet-admindata">
2392 <?php
2393 if (!$row['closure']) {
2394 ?>
2395 <div class="vbo-bookingdet-admin-entry">
2396 <label for="vbo-searchcust"><?php echo JText::translate($customer ? 'VBOASSIGNNEWCUST' : 'VBFILLCUSTFIELDS'); ?></label>
2397 <span style="display: block;"><?php echo JText::translate('VBOSEARCHEXISTCUST'); ?></span>
2398 <span class="vbo-eorder-assigncust" style="margin-bottom: 1px;">
2399 <input type="text" id="vbo-searchcust" autocomplete="off" value="" placeholder="<?php echo JText::translate('VBOSEARCHCUSTBY'); ?>" size="30" style="margin-bottom: 0;" />
2400 </span>
2401 <span id="vbo-searchcust-loading">
2402 <?php VikBookingIcons::e('hourglass-half'); ?>
2403 </span>
2404 <input type="hidden" name="newcustid" id="newcustid" value="" />
2405 <div id="vbo-searchcust-res" style="position: absolute; background-color: #fff;"></div>
2406 <span class="vbo-eorder-assignnewcust" style="display: block; margin-top: 10px;">
2407 <a class="vbo-assign-customer" href="index.php?option=com_vikbooking&task=newcustomer&bid=<?php echo $row['id']; ?>&goto=<?php echo base64_encode($gotouri.'#tab-admin'); ?>">
2408 <?php VikBookingIcons::e('user-circle'); ?>
2409 <span><?php echo JText::translate('VBOCREATENEWCUST'); ?></span>
2410 </a>
2411 </span>
2412
2413 <?php
2414 if (isset($adminSidebarForms['customer']))
2415 {
2416 echo $adminSidebarForms['customer'];
2417 }
2418 ?>
2419
2420 </div>
2421 <?php
2422 }
2423 ?>
2424 <div class="vbo-bookingdet-admin-entry">
2425 <label for="newpayment"><?php echo JText::translate('VBPAYMENTMETHOD'); ?></label>
2426 <?php
2427 if (is_array($payment)) {
2428 ?>
2429 <span><?php echo $payment['name']; ?></span>
2430 <?php
2431 }
2432 $chpayment = '';
2433 if ($payments) {
2434 $chpayment = '<div><select name="newpayment" id="newpayment" onchange="changePayment();"><option value="">'.JText::translate('VBCHANGEPAYLABEL').'</option>';
2435 foreach ($payments as $pay) {
2436 $chpayment .= '<option value="'.$pay['id'].'">'.(is_array($payment) && $payment['id'] == $pay['id'] ? ' ::' : '').$pay['name'].'</option>';
2437 }
2438 $chpayment .= '</select></div>';
2439 }
2440 echo $chpayment;
2441 ?>
2442
2443 <!-- Define role to detect the supported hook -->
2444 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderAdministrationSidebar","key":"payment","type":"field"} -->
2445
2446 <?php
2447 if (isset($adminSidebarForms['payment']))
2448 {
2449 echo $adminSidebarForms['payment'];
2450 }
2451 ?>
2452
2453 </div>
2454 <?php
2455 $tn = VikBooking::getTranslator();
2456 $all_langs = $tn->getLanguagesList();
2457 if (count($all_langs) > 1) {
2458 ?>
2459 <div class="vbo-bookingdet-admin-entry">
2460 <label for="newlang"><?php echo JText::translate('VBOBOOKINGLANG'); ?></label>
2461 <select name="newlang" id="newlang" onchange="document.adminForm.submit();">
2462 <?php
2463 foreach ($all_langs as $lk => $lv) {
2464 ?>
2465 <option value="<?php echo $lk; ?>"<?php echo $row['lang'] == $lk ? ' selected="selected"' : ''; ?>><?php echo isset($lv['nativeName']) ? $lv['nativeName'] : $lv['name']; ?></option>
2466 <?php
2467 }
2468 ?>
2469 </select>
2470
2471 <!-- Define role to detect the supported hook -->
2472 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderAdministrationSidebar","key":"language","type":"field"} -->
2473
2474 <?php
2475 if (isset($adminSidebarForms['language']))
2476 {
2477 echo $adminSidebarForms['language'];
2478 }
2479 ?>
2480 </div>
2481 <?php
2482 }
2483 ?>
2484
2485 <!-- Define role to detect the supported hook -->
2486 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderAdministrationSidebar","type":"fieldset"} -->
2487
2488 <?php
2489 foreach ($adminSidebarForms as $legend => $form)
2490 {
2491 if (in_array($legend, ['customer', 'payment', 'language']))
2492 {
2493 // skip default forms
2494 continue;
2495 }
2496 ?>
2497 <div class="vbo-bookingdet-admin-entry">
2498 <h3><?php echo JText::translate($legend); ?></h3>
2499
2500 <?php echo $form; ?>
2501 </div>
2502 <?php
2503 }
2504 ?>
2505
2506 </div>
2507 <div class="vbo-bookingdet-noteslogs">
2508 <?php
2509 $history = $history_obj->loadHistory();
2510 ?>
2511 <div class="vbo-bookingdet-noteslogs-btns">
2512 <div class="vbo-bookingdet-noteslogs-btn vbo-bookingdet-noteslogs-btn-active" data-id="notes">
2513 <a href="javascript: void(0);" id="vbo-trig-notes" onclick="javascript: vbToggleNotes(this);">
2514 <?php VikBookingIcons::e('user-lock'); ?>
2515 <span class="vbo-bookingdet-admintab-lbl"><?php echo JText::translate('VBADMINNOTESTOGGLE'); ?></span>
2516 </a>
2517 </div>
2518 <?php
2519 /**
2520 * Initialize chat instance by getting the proper channel name
2521 *
2522 * @since 1.12
2523 */
2524 if (empty($row['channel'])) {
2525 // front-end reservation chat handler
2526 $chat_channel = 'vikbooking';
2527 } else {
2528 $channelparts = explode('_', $row['channel']);
2529 // check if this is a meta search channel
2530 $is_meta_search = false;
2531 if (preg_match("/(customer).*[0-9]$/", $channelparts[0]) || !strcasecmp($channelparts[0], 'googlehotel') || !strcasecmp($channelparts[0], 'googlevr') || !strcasecmp($channelparts[0], 'trivago')) {
2532 $is_meta_search = empty($row['idorderota']);
2533 }
2534 if ($is_meta_search) {
2535 // customer of type sales channel should use front-end reservation chat handler
2536 $chat_channel = 'vikbooking';
2537 } else {
2538 // let the getInstance method validate the channel chat handler
2539 $chat_channel = $row['channel'];
2540 }
2541 }
2542 $messaging = VikBooking::getVcmChatInstance($row['id'], $chat_channel);
2543 //
2544 if (!$printreceipt && !is_null($messaging)) {
2545 ?>
2546 <div class="vbo-bookingdet-noteslogs-btn" data-id="messaging">
2547 <a name="messaging" href="javascript: void(0);" id="vbo-trig-messaging" onclick="javascript: vbToggleMessaging(this);">
2548 <?php VikBookingIcons::e('comment-dots'); ?>
2549 <span class="vbo-bookingdet-admintab-lbl"><?php echo JText::translate('VBO_GUEST_MESSAGING'); ?></span>
2550 </a>
2551 </div>
2552 <?php
2553 }
2554
2555 /**
2556 * Build up a tab to summarize the "takings" for this sole booking in case of relevant events.
2557 *
2558 * @since 1.16.9 (J) - 1.6.9 (WP)
2559 */
2560 $takings = [];
2561 if ($history) {
2562 // payment related events
2563 $h_payment_group = $history_obj->getTypeGroups($group = 'GPM');
2564
2565 // merge default types with 'PU' for the manually set "new amount paid" and with 'RU' (refunded amount updated)
2566 $takings_events = array_unique(array_merge(($h_payment_group['types'] ?? []), ['PU', 'RU']));
2567
2568 // load the relevant events with data
2569 $takings = $history_obj->getEventsWithData($takings_events, null, false);
2570
2571 if ($takings) {
2572 ?>
2573 <div class="vbo-bookingdet-noteslogs-btn pro-feature" data-id="takings">
2574 <a href="javascript: void(0);" id="vbo-trig-bookhistory" onclick="javascript: vbToggleDynamicPanel(this, '#vboextrapanel-takings');">
2575 <?php VikBookingIcons::e('wallet'); ?>
2576 <span class="vbo-bookingdet-admintab-lbl"><?php echo JText::translate('VBO_TAKINGS'); ?></span>
2577 </a>
2578 </div>
2579 <?php
2580 }
2581 }
2582
2583 if ($history) {
2584 ?>
2585 <div class="vbo-bookingdet-noteslogs-btn" data-id="history">
2586 <a href="javascript: void(0);" id="vbo-trig-bookhistory" onclick="javascript: vbToggleHistory(this);">
2587 <?php VikBookingIcons::e('history'); ?>
2588 <span class="vbo-bookingdet-admintab-lbl"><?php echo JText::translate('VBOBOOKHISTORYTAB'); ?></span>
2589 </a>
2590 </div>
2591 <script type="text/javascript">
2592 if (window.location.hash == '#bookhistory') {
2593 setTimeout(function() {
2594 jQuery(".vbo-bookingdet-tab[data-vbotab='vbo-tab-admin']").trigger('click');
2595 vbToggleHistory(document.getElementById('vbo-trig-bookhistory'));
2596 }, 500);
2597 }
2598 </script>
2599 <?php
2600 }
2601 ?>
2602 <div class="vbo-bookingdet-noteslogs-btn pro-feature" data-id="invnotes">
2603 <a href="javascript: void(0);" class="hasTooltip" id="vbo-trig-invnotes" onclick="javascript: vbToggleInvNotes(this);" title="<?php echo addslashes(JText::translate('VBBOOKINGINVNOTESHELP')); ?>">
2604 <?php VikBookingIcons::e('file-invoice'); ?>
2605 <span class="vbo-bookingdet-admintab-lbl"><?php echo JText::translate('VBBOOKINGINVNOTES'); ?></span>
2606 </a>
2607 </div>
2608
2609 <!-- Define role to detect the supported hook -->
2610 <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderAdministration","type":"fieldset"} -->
2611
2612 <?php
2613 foreach ($adminPanelForms as $legend => $form)
2614 {
2615 $legendId = preg_replace("/[^a-zA-Z0-9_\-]+/", '', $legend);
2616 ?>
2617 <div class="vbo-bookingdet-noteslogs-btn" data-id="<?php echo $legendId; ?>">
2618 <a href="javascript: void(0);" class="hasTooltip" id="vbo-trig-<?php echo $legendId; ?>" onclick="javascript: vbToggleDynamicPanel(this, '#vboextrapanel-<?php echo $legendId; ?>');">
2619 <?php VikBookingIcons::e(!empty($adminFormsSetup->icons[$legend]) ? $adminFormsSetup->icons[$legend] : 'plug'); ?>
2620 <span class="vbo-bookingdet-admintab-lbl"><?php echo JText::translate($legend); ?></span>
2621 </a>
2622 </div>
2623 <?php
2624 }
2625
2626 if (!empty($row['paymentlog'])) {
2627 $paylogs_lbl = JText::translate('VBPAYMENTLOGTOGGLE');
2628 if ($may_have_cc_details) {
2629 $paylogs_lbl = JText::translate('VBO_CREDIT_CARD');
2630 }
2631 ?>
2632 <div class="vbo-bookingdet-noteslogs-btn" data-id="paylogs">
2633 <a href="javascript: void(0);" id="vbo-trig-paylogs" onclick="javascript: vbToggleLog(this);">
2634 <?php VikBookingIcons::e('credit-card'); ?>
2635 <span class="vbo-bookingdet-admintab-lbl"><?php echo $paylogs_lbl; ?></span>
2636 </a>
2637 <a name="paymentlog" href="javascript: void(0);"></a>
2638 </div>
2639 <?php
2640 }
2641 ?>
2642 </div>
2643 <div class="vbo-bookingdet-noteslogs-cont">
2644 <div id="vbadminnotesdiv" class="vbo-extra-panel" style="display: block;">
2645 <textarea name="adminnotes" class="vbadminnotestarea"><?php echo strip_tags((string)$row['adminnotes']); ?></textarea>
2646 <input type="submit" name="updadmnotes" value="<?php echo JText::translate('VBADMINNOTESUPD'); ?>" class="btn btn-success" />
2647 </div>
2648 <?php
2649 if ($takings) {
2650 ?>
2651 <div class="vbo-extra-panel" id="vboextrapanel-takings" style="display: none;">
2652 <div class="vbo-booking-takings-container table-responsive">
2653 <table class="table">
2654 <thead>
2655 <tr class="vbo-booking-takings-firstrow">
2656 <td class="vbo-booking-takings-td-totpaid"><?php echo JText::translate('VBO_TAKINGS'); ?></td>
2657 <td class="vbo-booking-takings-td-date"><?php echo JText::translate('VBOBOOKHISTORYLBLDATE'); ?></td>
2658 <td class="vbo-booking-takings-td-type"><?php echo JText::translate('VBOBOOKHISTORYLBLTYPE'); ?></td>
2659 <td class="vbo-booking-takings-td-fees"><?php echo JText::translate('VBO_PROCESSING_FEES'); ?></td>
2660 <td class="vbo-booking-takings-td-descr"><?php echo JText::translate('VBOBOOKHISTORYLBLDESC'); ?></td>
2661 </tr>
2662 </thead>
2663 <tbody>
2664 <?php
2665 $booking_total_taking = 0;
2666 $booking_total_prfees = 0;
2667 foreach (array_reverse($takings) as $hist) {
2668 // calculate amount paid and description
2669 $tn_amount_paid = 0;
2670 $tn_amount_fees = 0;
2671 $tn_description = strpos((string) $hist['descr'], '<') !== false ? $hist['descr'] : preg_replace("/\R/", ' - ', (string) $hist['descr']);
2672 if (is_object($hist['data'])) {
2673 // calculate amount paid or amount refunded
2674 if (($hist['data']->amount_paid ?? 0)) {
2675 $tn_amount_paid = $hist['data']->amount_paid;
2676 if (in_array($hist['type'], ['RF', 'RU'])) {
2677 // turn the amount paid to negative
2678 $tn_amount_paid = $tn_amount_paid < 0 ? $tn_amount_paid : ($tn_amount_paid - ($tn_amount_paid * 2));
2679 if ($hist['type'] === 'RU' && $hist['data']->amount_paid < 0) {
2680 // this indicates a lower amount refunded, so we double it to make it positive
2681 $tn_amount_paid = abs($hist['data']->amount_paid);
2682 }
2683 }
2684 }
2685
2686 // calculate processing fees, if set and if any
2687 if (($hist['data']->processing_fees ?? 0)) {
2688 $tn_amount_fees += $hist['data']->processing_fees;
2689 }
2690
2691 // build the event description
2692 if (($hist['data']->payment_method ?? '')) {
2693 $tn_description = ucwords($hist['data']->payment_method);
2694 } elseif (($hist['data']->driver ?? '')) {
2695 $tn_description = ucwords(str_replace('_', ' ', basename($hist['data']->driver, '.php')));
2696 }
2697 }
2698
2699 // increase (or decrease) booking total takings and processing fees amounts
2700 $booking_total_taking += $tn_amount_paid;
2701 $booking_total_prfees += $tn_amount_fees;
2702 ?>
2703 <tr class="vbo-booking-takings-row">
2704 <td>
2705 <?php
2706 echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($tn_amount_paid), $currencysymb);
2707 if (!strcasecmp($hist['type'], 'PU')) {
2708 /**
2709 * Allow to edit or delete the history record.
2710 *
2711 * @since 1.16.10 (J) - 1.6.10 (WP)
2712 */
2713 ?>
2714 <div class="vbo-booking-taking-cmds">
2715 <button type="button" class="btn btn-small btn-primary vbo-booking-taking-edit vbo-tooltip vbo-tooltip-top" data-tooltiptext="<?php echo $this->escape(JText::translate('VBMAINPAYMENTSEDIT')); ?>" data-historyid="<?php echo $hist['id']; ?>" data-amount="<?php echo $tn_amount_paid; ?>"><?php VikBookingIcons::e('edit'); ?></button>
2716 <button type="button" class="btn btn-small btn-danger vbo-booking-taking-delete vbo-tooltip vbo-tooltip-top" data-tooltiptext="<?php echo $this->escape(JText::translate('VBELIMINA')); ?>" data-historyid="<?php echo $hist['id']; ?>"><?php VikBookingIcons::e('times-circle'); ?></button>
2717 </div>
2718 <?php
2719 }
2720 ?>
2721 </td>
2722 <td><?php echo JHtml::fetch('date', $hist['dt'], 'Y-m-d H:i:s'); ?></td>
2723 <td><?php echo $history_obj->validType($hist['type'], true); ?></td>
2724 <td><?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($tn_amount_fees), $currencysymb); ?></td>
2725 <td><?php echo $tn_description; ?></td>
2726 </tr>
2727 <?php
2728 }
2729 ?>
2730 </tbody>
2731 <tfoot>
2732 <tr>
2733 <td colspan="2">
2734 <span><?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($booking_total_taking), $currencysymb); ?></span>
2735 </td>
2736 <td></td>
2737 <td>
2738 <span><?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($booking_total_prfees), $currencysymb); ?></span>
2739 </td>
2740 <td>
2741 <button type="button" class="btn btn-small btn-success vbo-takings-addnew"><?php VikBookingIcons::e('plus-circle'); ?> <?php echo JText::translate('VBO_REG_NEW_PAYMENT'); ?></button>
2742 </td>
2743 </tr>
2744 </tfoot>
2745 </table>
2746 </div>
2747
2748 <div class="vbo-eorder-newtaking-helper-wrap" style="display: none;">
2749 <div class="vbo-eorder-newtaking-helper-cont">
2750 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
2751 <div class="vbo-params-wrap">
2752 <div class="vbo-params-container">
2753 <div class="vbo-params-block">
2754 <div class="vbo-param-container">
2755 <div class="vbo-param-label">
2756 <label for="new_taking_amount"><?php echo JText::translate('VBO_CC_AMOUNT'); ?></label>
2757 </div>
2758 <div class="vbo-param-setting">
2759 <div class="vbo-input-currency-wrap">
2760 <span><?php echo $currencysymb; ?></span>
2761 <input type="number" id="new_taking_amount" value="" min="0" max="<?php echo $row['total']; ?>" step="any" />
2762 </div>
2763 <span class="vbo-param-setting-comment">
2764 <?php echo JText::translate('VBOCUSTOMERCMMSONTOTAL') . ' ' . VikBooking::formatCurrencyNumber(VikBooking::numberFormat($row['total']), $currencysymb) . ' - ' . JText::translate('VBAMOUNTPAID') . ' ' . VikBooking::formatCurrencyNumber(VikBooking::numberFormat($row['totpaid']), $currencysymb); ?>
2765 </span>
2766 </div>
2767 </div>
2768 <div class="vbo-param-container">
2769 <div class="vbo-param-label">
2770 <label for="new_taking_descr"><?php echo JText::translate('VBLIBPAYNAME'); ?></label>
2771 </div>
2772 <div class="vbo-param-setting">
2773 <select id="new_taking_payid">
2774 <option value="">&nbsp;</option>
2775 <?php
2776 foreach ($this->payments as $paymeth) {
2777 ?>
2778 <option value="<?php echo $paymeth['id']; ?>"><?php echo $paymeth['name']; ?></option>
2779 <?php
2780 }
2781 ?>
2782 </select>
2783 </div>
2784 </div>
2785 <div class="vbo-param-container vbo-param-nested" id="vbo-new-taking-custom-wrap">
2786 <div class="vbo-param-label">&nbsp;</div>
2787 <div class="vbo-param-setting">
2788 <input id="new_taking_descr" type="text" value="" maxlength="200" placeholder="<?php echo $this->escape(JText::translate('VBPVIEWOPTIONALSTWO')); ?>" />
2789 </div>
2790 </div>
2791 </div>
2792 </div>
2793 </div>
2794 </div>
2795 </div>
2796 </div>
2797
2798 </div>
2799
2800 <script type="text/javascript">
2801 jQuery(function() {
2802
2803 jQuery('#new_taking_payid').on('change', function() {
2804 if (jQuery(this).val()) {
2805 jQuery('#vbo-new-taking-custom-wrap').hide();
2806 jQuery('#new_taking_descr').val('');
2807 } else {
2808 jQuery('#vbo-new-taking-custom-wrap').show();
2809 }
2810 });
2811
2812 jQuery('.vbo-takings-addnew').on('click', function() {
2813 // build modal buttons
2814 let footer_left = jQuery('<button></button>');
2815 footer_left.addClass('btn');
2816 footer_left.attr('type', 'button');
2817 footer_left.text(Joomla.JText._('VBANNULLA'));
2818 footer_left.on('click', function() {
2819 // dismiss the modal
2820 VBOCore.emitEvent('vbo-eorder-new-taking-dismiss');
2821 });
2822
2823 let footer_right = jQuery('<button></button>');
2824 footer_right.addClass('btn btn-success');
2825 footer_right.attr('type', 'button');
2826 footer_right.text(Joomla.JText._('VBSAVE'));
2827 footer_right.on('click', function() {
2828 // disable button to prevent double submissions
2829 let submit_btn = jQuery(this);
2830 submit_btn.prop('disabled', true);
2831 // make the request
2832 VBOCore.doAjax(
2833 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.add_taking'); ?>",
2834 {
2835 bid: '<?php echo $row['id']; ?>',
2836 amount: jQuery('#new_taking_amount').val(),
2837 payid: jQuery('#new_taking_payid').val(),
2838 descr: jQuery('#new_taking_descr').val(),
2839 },
2840 (success) => {
2841 // dismiss the modal
2842 VBOCore.emitEvent('vbo-eorder-new-taking-dismiss');
2843 // reload the page by following the response URL
2844 document.location.href = success.url;
2845 },
2846 (error) => {
2847 // re-enable submit button
2848 submit_btn.prop('disabled', false);
2849 // display error message
2850 alert(error.responseText);
2851 }
2852 );
2853 });
2854
2855 // display modal
2856 let modal_body = VBOCore.displayModal({
2857 suffix: 'vbo-new-taking',
2858 extra_class: 'vbo-modal-rounded vbo-modal-dialog',
2859 title: Joomla.JText._('VBO_REG_NEW_PAYMENT'),
2860 body: '',
2861 body_prepend: true,
2862 footer_left: footer_left,
2863 footer_right: footer_right,
2864 draggable: true,
2865 dismiss_event: 'vbo-eorder-new-taking-dismiss',
2866 onDismiss: () => {
2867 jQuery('.vbo-eorder-newtaking-helper-cont').appendTo(
2868 jQuery('.vbo-eorder-newtaking-helper-wrap')
2869 );
2870 },
2871 });
2872
2873 // reset helper input values
2874 jQuery('#new_taking_amount').val('');
2875 jQuery('#new_taking_payid').prop('disabled', false).val('').trigger('change');
2876 jQuery('#new_taking_descr').val('');
2877
2878 // append modal body
2879 jQuery('.vbo-eorder-newtaking-helper-cont').appendTo(modal_body);
2880 });
2881
2882 jQuery('.vbo-booking-taking-edit').on('click', function() {
2883 let edit_btn = jQuery(this);
2884 let history_id = edit_btn.attr('data-historyid');
2885 let curr_amount_paid = edit_btn.attr('data-amount');
2886 let curr_pay_descr = edit_btn.closest('tr.vbo-booking-takings-row').find('td').last().text();
2887
2888 // build modal buttons
2889 let footer_left = jQuery('<button></button>');
2890 footer_left.addClass('btn');
2891 footer_left.attr('type', 'button');
2892 footer_left.text(Joomla.JText._('VBANNULLA'));
2893 footer_left.on('click', function() {
2894 // dismiss the modal
2895 VBOCore.emitEvent('vbo-eorder-edit-taking-dismiss');
2896 });
2897
2898 let footer_right = jQuery('<button></button>');
2899 footer_right.addClass('btn btn-success');
2900 footer_right.attr('type', 'button');
2901 footer_right.text(Joomla.JText._('VBO_UPDATE_PAYMENT'));
2902 footer_right.on('click', function() {
2903 // disable button to prevent double submissions
2904 let submit_btn = jQuery(this);
2905 submit_btn.prop('disabled', true);
2906 // make the request
2907 VBOCore.doAjax(
2908 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.update_taking'); ?>",
2909 {
2910 bid: '<?php echo $row['id']; ?>',
2911 hid: history_id,
2912 amount: jQuery('#new_taking_amount').val(),
2913 descr: jQuery('#new_taking_descr').val(),
2914 htype: 'PU',
2915 },
2916 (success) => {
2917 // dismiss the modal
2918 VBOCore.emitEvent('vbo-eorder-edit-taking-dismiss');
2919 // reload the page by following the response URL
2920 document.location.href = success.url;
2921 },
2922 (error) => {
2923 // re-enable submit button
2924 submit_btn.prop('disabled', false);
2925 // display error message
2926 alert(error.responseText);
2927 }
2928 );
2929 });
2930
2931 // display modal
2932 let modal_body = VBOCore.displayModal({
2933 suffix: 'vbo-edit-taking',
2934 extra_class: 'vbo-modal-rounded vbo-modal-dialog',
2935 title: Joomla.JText._('VBO_UPDATE_PAYMENT'),
2936 body: '',
2937 body_prepend: true,
2938 footer_left: footer_left,
2939 footer_right: footer_right,
2940 draggable: true,
2941 dismiss_event: 'vbo-eorder-edit-taking-dismiss',
2942 onDismiss: () => {
2943 jQuery('.vbo-eorder-newtaking-helper-cont').appendTo(
2944 jQuery('.vbo-eorder-newtaking-helper-wrap')
2945 );
2946 },
2947 });
2948
2949 // populate helper input values
2950 jQuery('#new_taking_amount').val(curr_amount_paid);
2951 jQuery('#new_taking_payid').val('').trigger('change').prop('disabled', true);
2952 jQuery('#new_taking_descr').val(curr_pay_descr);
2953
2954 // append modal body
2955 jQuery('.vbo-eorder-newtaking-helper-cont').appendTo(modal_body);
2956 });
2957
2958 jQuery('.vbo-booking-taking-delete').on('click', function() {
2959 if (!confirm(Joomla.JText._('VBDELCONFIRM'))) {
2960 return false;
2961 }
2962 let del_btn = jQuery(this);
2963 del_btn.prop('disabled', true);
2964 let history_id = del_btn.attr('data-historyid');
2965 // make the request
2966 VBOCore.doAjax(
2967 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.delete_history_record'); ?>",
2968 {
2969 bid: '<?php echo $row['id']; ?>',
2970 hid: history_id,
2971 htype: 'PU',
2972 },
2973 (success) => {
2974 // reload the page by following the response URL
2975 document.location.href = success.url;
2976 },
2977 (error) => {
2978 // re-enable delete button
2979 del_btn.prop('disabled', false);
2980 // display error message
2981 alert(error.responseText);
2982 }
2983 );
2984 });
2985
2986 });
2987 </script>
2988 <?php
2989 }
2990 if ($history) {
2991 ?>
2992 <div id="vbhistorydiv" class="vbo-extra-panel" style="display: none;">
2993 <div class="vbo-booking-history-container table-responsive">
2994 <table class="table">
2995 <thead>
2996 <tr class="vbo-booking-history-firstrow">
2997 <td class="vbo-booking-history-td-type"><?php echo JText::translate('VBOBOOKHISTORYLBLTYPE'); ?></td>
2998 <td class="vbo-booking-history-td-date"><?php echo JText::translate('VBOBOOKHISTORYLBLDATE'); ?></td>
2999 <td class="vbo-booking-history-td-descr"><?php echo JText::translate('VBOBOOKHISTORYLBLDESC'); ?></td>
3000 <td class="vbo-booking-history-td-totpaid"><?php echo JText::translate('VBOBOOKHISTORYLBLTPAID'); ?></td>
3001 <td class="vbo-booking-history-td-tot"><?php echo JText::translate('VBOBOOKHISTORYLBLTOT'); ?></td>
3002 </tr>
3003 </thead>
3004 <tbody>
3005 <?php
3006 foreach ($history as $hist) {
3007 $hdescr = strpos((string) $hist['descr'], '<') !== false ? $hist['descr'] : nl2br((string) $hist['descr']);
3008 ?>
3009 <tr class="vbo-booking-history-row">
3010 <td><?php echo $history_obj->validType($hist['type'], true); ?></td>
3011 <td><?php echo JHtml::fetch('date', $hist['dt'], 'Y-m-d H:i:s'); ?></td>
3012 <td><?php echo $hdescr; ?></td>
3013 <td><?php echo $currencyname.' '.VikBooking::numberFormat($hist['totpaid']); ?></td>
3014 <td><?php echo $currencyname.' '.VikBooking::numberFormat($hist['total']); ?></td>
3015 </tr>
3016 <?php
3017 }
3018 ?>
3019 </tbody>
3020 </table>
3021 </div>
3022 </div>
3023 <?php
3024 }
3025 ?>
3026 <div id="vbinvnotesdiv" class="vbo-extra-panel" style="display: none;">
3027 <textarea name="invnotes" id="invnotes" class="vbadminnotestarea"><?php echo $row['inv_notes']; ?></textarea>
3028 <input type="submit" name="updinvnotes" value="<?php echo JText::translate('VBADMINNOTESUPD'); ?>" class="btn btn-success" />
3029 <button type="button" class="btn vbo-config-btn btn-secondary pull-right" onclick="document.getElementById('invnotes-hid').value=document.getElementById('invnotes').value;document.getElementById('vbo-gen-invoice').submit();"><?php VikBookingIcons::e('file-invoice'); ?> <?php echo JText::translate('VBOGENBOOKINGINVOICE'); ?></button>
3030 </div>
3031 <?php
3032 if (!empty($row['paymentlog'])) {
3033 ?>
3034 <div id="vbpaymentlogdiv" class="vbo-extra-panel" style="display: none;">
3035 <div class="vbo-eorder-paymentlog-buttons">
3036 <?php
3037 // PCI Data Retrieval
3038 $cc_acl_denied = false;
3039 if (!empty($row['idorderota']) && !empty($row['channel'])) {
3040 $channel_source = $row['channel'];
3041 if (strpos($row['channel'], '_') !== false) {
3042 $channelparts = explode('_', $row['channel']);
3043 $channel_source = $channelparts[0];
3044 }
3045 $checkout_info = getdate($row['checkout']);
3046
3047 // validate ACL for credit card details
3048 if (!$canDo->authorise('core.admin', 'com_vikchannelmanager')) {
3049 // permissions to access VCM are required
3050 $cc_acl_denied = true;
3051 ?>
3052 <p class="err"><?php echo JText::translate('JERROR_ALERTNOAUTHOR'); ?></p>
3053 <?php
3054 } else {
3055 /**
3056 * Limit for accessing the credit card details has been changed to check-out
3057 * day at 23:59:59 + 10 extra days. It used to be at 23:59:59 on check-out day.
3058 *
3059 * @since 1.13
3060 */
3061 $cardlimit = mktime(23, 59, 59, $checkout_info['mon'], ($checkout_info['mday'] + 10), $checkout_info['year']);
3062 if ($current_ts < $cardlimit && $may_have_cc_details) {
3063 // log contains credit card details
3064 // prepare modal (Credit Card Details)
3065 array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-pcid', JText::translate('GETFULLCARDDETAILS'), '', 'width: 80%; height: 60%; margin-left: -40%; top: 20% !important;'));
3066 ?>
3067 <div class="vcm-notif-pcidrq-container">
3068 <button type="button" class="btn vbo-config-btn vcm-pcid-launch" onclick="vboOpenJModal('vbo-vcm-pcid', 'index.php?option=com_vikchannelmanager&task=execpcid&channel_source=<?php echo $channel_source; ?>&otaid=<?php echo $row['idorderota']; ?>&tmpl=component');"><?php VikBookingIcons::e('credit-card'); ?> <?php echo JText::translate('GETFULLCARDDETAILS'); ?></button>
3069 </div>
3070 <?php
3071 /**
3072 * Check for automatic payment schedules support when an active CC/VCC is available.
3073 *
3074 * @since 1.16.10 (J) - 1.6.10 (WP)
3075 */
3076 $can_payschedule = false;
3077 $active_payschedules = [];
3078 try {
3079 $processor = VBOModelReservation::getInstance($row, true)->getPaymentProcessor();
3080 if (method_exists($processor, 'isDirectChargeSupported') && $processor->isDirectChargeSupported()) {
3081 // turn flag on
3082 $can_payschedule = true;
3083 // load current schedules
3084 $active_payschedules = VBOModelPayschedules::getInstance()->getItems([
3085 'idorder' => [
3086 'value' => $row['id'],
3087 ],
3088 ]);
3089 }
3090 } catch (Exception $e) {
3091 // do nothing
3092 }
3093
3094 if ($can_payschedule) {
3095 // calculate the total amount scheduled
3096 $tot_scheduled = 0;
3097 foreach ($active_payschedules as $active_payschedule) {
3098 if (!$active_payschedule->status) {
3099 $tot_scheduled += $active_payschedule->amount;
3100 }
3101 }
3102
3103 // display action buttons for payment schedules
3104 ?>
3105 <div class="vbo-eorder-payschedules-wrap">
3106 <button type="button" class="btn btn-<?php echo $active_payschedules || $automatic_payment_collection ? 'success' : 'primary'; ?> vbo-context-menu-btn vbo-context-menu-payschedules">
3107 <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBO_AUTOPAY_SCHEDULED'); ?></span>
3108 <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('sort-down'); ?></span>
3109 </button>
3110 </div>
3111
3112 <div class="vbo-eorder-newpayschedule-helper-wrap" style="display: none;">
3113 <div class="vbo-eorder-newpayschedule-helper-cont" data-auto-pay-schedules="<?php echo (int) $automatic_payment_collection; ?>">
3114 <p class="info" data-auto-pay-schedules="help" style="display: none;"><?php echo JText::translate('VBO_AUTO_PAY_COLLECT_HELP'); ?></p>
3115 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
3116 <div class="vbo-params-wrap">
3117 <div class="vbo-params-container">
3118 <div class="vbo-params-block">
3119 <div class="vbo-param-container">
3120 <div class="vbo-param-label">
3121 <label for="new_payschedule_amount"><?php echo JText::translate('VBO_CC_AMOUNT'); ?></label>
3122 </div>
3123 <div class="vbo-param-setting">
3124 <div class="vbo-input-currency-wrap">
3125 <span><?php echo $currencysymb; ?></span>
3126 <input type="number" id="new_payschedule_amount" value="<?php echo $tot_scheduled < $row['total'] ? ($row['total'] - $tot_scheduled) : 0; ?>" min="0" step="any" />
3127 </div>
3128 <span class="vbo-param-setting-comment"><?php echo JText::translate('VBEDITORDERNINE') . ' ' . VikBooking::formatCurrencyNumber(VikBooking::numberFormat($row['total']), $currencysymb); ?></span>
3129 </div>
3130 </div>
3131 <div class="vbo-param-container">
3132 <div class="vbo-param-label">
3133 <label for="new_payschedule_fordt"><?php echo JText::translate('VBPVIEWORDERSONE'); ?></label>
3134 </div>
3135 <div class="vbo-param-setting">
3136 <?php echo $vbo_app->getCalendar(date($df, $row['checkin']), 'new_payschedule_fordt', 'new_payschedule_fordt', $nowdf, array('class'=>'', 'size'=>'10', 'maxlength'=>'19', 'todayBtn' => 'true')); ?>
3137 </div>
3138 </div>
3139 <div class="vbo-param-container">
3140 <div class="vbo-param-label">
3141 <label for="new_payschedule_fordtime"><?php echo JText::translate('VBO_REMINDER_TIME'); ?></label>
3142 </div>
3143 <div class="vbo-param-setting">
3144 <select id="new_payschedule_fordtime">
3145 <?php
3146 for ($h = 0; $h < 24; $h++) {
3147 $say_htime = ($h < 10 ? '0' : '') . $h;
3148 ?>
3149 <option value="<?php echo $say_htime; ?>:00"><?php echo $say_htime; ?>:00</option>
3150 <option value="<?php echo $say_htime; ?>:30"><?php echo $say_htime; ?>:30</option>
3151 <?php
3152 }
3153 ?>
3154 </select>
3155 </div>
3156 </div>
3157 </div>
3158 </div>
3159 </div>
3160 </div>
3161 </div>
3162 </div>
3163
3164 <script type="text/javascript">
3165
3166 // build base buttons list for context menu
3167 var vbo_payschedule_btns = [
3168 // toggle automatic payment collection scheduling for all bookings
3169 {
3170 activeState: <?php echo $automatic_payment_collection ? 'true' : 'false'; ?>,
3171 text: <?php echo json_encode(JText::translate('VBO_ENABLED_FOR_ALL_BOOKINGS')); ?>,
3172 separator: true,
3173 icon: function() {
3174 return this.activeState ? '<?php echo VikBookingIcons::i('toggle-on', 'vbo-enabled-icon'); ?>' : '<?php echo VikBookingIcons::i('toggle-off'); ?>';
3175 },
3176 action: function(root, event) {
3177 // create reference to button object
3178 let that = this;
3179
3180 // get new state
3181 let newState = !this.activeState;
3182
3183 // determine confirmation message
3184 let confirm_enable = <?php echo json_encode(JText::translate('VBO_AUTO_PAY_COLLECT_ENABLE_CONF')); ?>;
3185 let confirm_disable = <?php echo json_encode(JText::translate('VBO_AUTO_PAY_COLLECT_DISABLE_CONF')); ?>;
3186
3187 if ((newState && confirm(confirm_enable)) || (!newState && confirm(confirm_disable))) {
3188 // silently update configuration setting
3189 VBOCore.doAjax(
3190 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=configuration.update'); ?>",
3191 {
3192 settings: {
3193 auto_payment_collection: newState ? 1 : 0,
3194 }
3195 },
3196 (success) => {
3197 // toggle state
3198 that.activeState = newState;
3199 // update data attribute with the newly saved configuration value
3200 let statusEl = document.querySelector('.vbo-eorder-newpayschedule-helper-cont[data-auto-pay-schedules]');
3201 if (statusEl) {
3202 statusEl.setAttribute('data-auto-pay-schedules', (newState ? 1 : 0));
3203 }
3204 },
3205 (error) => {
3206 console.error(error);
3207 }
3208 );
3209 }
3210 },
3211 },
3212 // add new payment schedule button
3213 {
3214 icon: '<?php echo VikBookingIcons::i('plus-circle'); ?>',
3215 text: Joomla.JText._('VBO_NEW_PAYSCHEDULE'),
3216 separator: true,
3217 action: (root, config) => {
3218 // build modal buttons
3219 let footer_left = jQuery('<button></button>');
3220 footer_left.addClass('btn');
3221 footer_left.attr('type', 'button');
3222 footer_left.text(Joomla.JText._('VBANNULLA'));
3223 footer_left.on('click', function() {
3224 // dismiss the modal
3225 VBOCore.emitEvent('vbo-eorder-new-payschedule-dismiss');
3226 });
3227
3228 let footer_right = jQuery('<button></button>');
3229 footer_right.addClass('btn btn-success');
3230 footer_right.attr('type', 'button');
3231 footer_right.text(Joomla.JText._('VBSAVE'));
3232 footer_right.on('click', function() {
3233 // disable button to prevent double submissions
3234 let submit_btn = jQuery(this);
3235 submit_btn.prop('disabled', true);
3236 // make the request
3237 VBOCore.doAjax(
3238 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=payschedules.save'); ?>",
3239 {
3240 bid: '<?php echo $row['id']; ?>',
3241 amount: jQuery('#new_payschedule_amount').val(),
3242 dt: jQuery('#new_payschedule_fordt').val(),
3243 time: jQuery('#new_payschedule_fordtime').val(),
3244 },
3245 (new_pay_schedules) => {
3246 // re-enable submit button
3247 submit_btn.prop('disabled', false);
3248 // dismiss the modal
3249 VBOCore.emitEvent('vbo-eorder-new-payschedule-dismiss');
3250 // populate the new schedule buttons
3251 let new_pay_schedule_btns = [];
3252 // push button to toggle automatic payment collection scheduling for all bookings
3253 new_pay_schedule_btns.push(vbo_payschedule_btns[0]);
3254 // push button to add a new schedule
3255 new_pay_schedule_btns.push(vbo_payschedule_btns[1]);
3256 // push all active schedules
3257 new_pay_schedules.forEach((payschedule) => {
3258 new_pay_schedule_btns.push(
3259 vboBuildPayScheduleBtn(payschedule)
3260 );
3261 });
3262 // update trigger button class
3263 if (new_pay_schedules.length) {
3264 jQuery('.vbo-context-menu-payschedules').removeClass('btn-primary').addClass('btn-success');
3265 } else {
3266 jQuery('.vbo-context-menu-payschedules').removeClass('btn-success').addClass('btn-primary');
3267 }
3268 // set new buttons in context menu
3269 jQuery('.vbo-context-menu-payschedules').vboContextMenu('buttons', new_pay_schedule_btns);
3270 },
3271 (error) => {
3272 // re-enable submit button
3273 submit_btn.prop('disabled', false);
3274 // display error message
3275 alert(error.responseText);
3276 }
3277 );
3278 });
3279
3280 // display modal
3281 let modal_body = VBOCore.displayModal({
3282 suffix: 'vbo-new-pay-schedule',
3283 extra_class: 'vbo-modal-rounded vbo-modal-dialog',
3284 title: Joomla.JText._('VBO_NEW_PAYSCHEDULE'),
3285 body: '',
3286 body_prepend: true,
3287 footer_left: footer_left,
3288 footer_right: footer_right,
3289 draggable: true,
3290 dismiss_event: 'vbo-eorder-new-payschedule-dismiss',
3291 onDismiss: () => {
3292 jQuery('.vbo-eorder-newpayschedule-helper-cont').appendTo(
3293 jQuery('.vbo-eorder-newpayschedule-helper-wrap')
3294 );
3295 },
3296 });
3297
3298 // check current automatic payment schedules status
3299 let statusEl = document.querySelector('.vbo-eorder-newpayschedule-helper-cont[data-auto-pay-schedules]');
3300 if (statusEl) {
3301 let autoPayStatus = statusEl.getAttribute('data-auto-pay-schedules');
3302 if (autoPayStatus == 1) {
3303 // show help element
3304 statusEl.querySelector('[data-auto-pay-schedules="help"]').style.display = '';
3305 } else {
3306 // hide help element
3307 statusEl.querySelector('[data-auto-pay-schedules="help"]').style.display = 'none';
3308 }
3309 }
3310
3311 // append modal body
3312 jQuery('.vbo-eorder-newpayschedule-helper-cont').appendTo(modal_body);
3313 },
3314 }
3315 ];
3316
3317 /**
3318 * Builds a button object for the context menu from the given payment schedule object.
3319 */
3320 function vboBuildPayScheduleBtn(payschedule) {
3321 let icn_to_process = '<?php echo VikBookingIcons::i('clock'); ?>';
3322 let icn_processed = '<?php echo VikBookingIcons::i('check-circle'); ?>';
3323 let icn_error = '<?php echo VikBookingIcons::i('exclamation-triangle'); ?>';
3324 let dt_unit = (payschedule.dt_diff.days || payschedule.dt_diff.weeks || payschedule.dt_diff.months || payschedule.dt_diff.years || 0);
3325 let say_dt = !payschedule.dt_diff.past && dt_unit > 0 ? payschedule.dt_diff.relative : payschedule?.fordt;
3326 if (!payschedule.dt_diff.past && (payschedule.dt_diff.sameday || payschedule.dt_diff.today)) {
3327 say_dt = payschedule.dt_diff.relative + ' (' + payschedule.time_hm + ')';
3328 } else if (!payschedule.dt_diff.past && payschedule.dt_diff.tomorrow) {
3329 say_dt = payschedule.dt_diff.relative + ' (' + payschedule.time_hm + ')';
3330 }
3331
3332 return {
3333 icon: ((payschedule.status || 0) > 0 ? (payschedule.status == 1 ? icn_processed : icn_error) : icn_to_process),
3334 text: VBOCore.getCurrency().format(payschedule?.amount) + ' - ' + say_dt,
3335 class: ((payschedule.status || 0) == 1 ? 'vbo-context-menu-entry-success' : ((payschedule.status || 0) == 2 ? 'vbo-context-menu-entry-warning' : 'vbo-context-menu-entry-danger')),
3336 separator: false,
3337 action: (root, config) => {
3338 if (payschedule.status == 0 || !payschedule.logs) {
3339 // confirm deletion without displaying anything
3340 if (confirm(Joomla.JText._('VBDELCONFIRM'))) {
3341 // make the request
3342 VBOCore.doAjax(
3343 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=payschedules.delete'); ?>",
3344 {
3345 bid: payschedule.idorder,
3346 schedule_id: payschedule.id,
3347 },
3348 (new_pay_schedules) => {
3349 // populate the new schedule buttons
3350 let new_pay_schedule_btns = [];
3351 // push button to toggle automatic payment collection scheduling for all bookings
3352 new_pay_schedule_btns.push(vbo_payschedule_btns[0]);
3353 // push button to add a new schedule
3354 new_pay_schedule_btns.push(vbo_payschedule_btns[1]);
3355 // push all active schedules
3356 new_pay_schedules.forEach((payschedule) => {
3357 new_pay_schedule_btns.push(
3358 vboBuildPayScheduleBtn(payschedule)
3359 );
3360 });
3361 // update trigger button class
3362 if (new_pay_schedules.length) {
3363 jQuery('.vbo-context-menu-payschedules').removeClass('btn-primary').addClass('btn-success');
3364 } else {
3365 jQuery('.vbo-context-menu-payschedules').removeClass('btn-success').addClass('btn-primary');
3366 }
3367 // set new buttons in context menu
3368 jQuery('.vbo-context-menu-payschedules').vboContextMenu('buttons', new_pay_schedule_btns);
3369 },
3370 (error) => {
3371 // display error message
3372 alert(error.responseText);
3373 }
3374 );
3375 }
3376 } else {
3377 // display modal on click with the execution logs
3378
3379 // build modal buttons
3380 let footer_left = jQuery('<button></button>');
3381 footer_left.addClass('btn');
3382 footer_left.attr('type', 'button');
3383 footer_left.text(Joomla.JText._('VBANNULLA'));
3384 footer_left.on('click', function() {
3385 // dismiss the modal
3386 VBOCore.emitEvent('vbo-eorder-payschedule-logs-dismiss');
3387 });
3388
3389 let footer_right = jQuery('<button></button>');
3390 footer_right.addClass('btn btn-danger');
3391 footer_right.attr('type', 'button');
3392 footer_right.text(Joomla.JText._('VBELIMINA'));
3393 footer_right.on('click', function() {
3394 // confirm record deletion
3395 if (confirm(Joomla.JText._('VBDELCONFIRM'))) {
3396 // make the request
3397 VBOCore.doAjax(
3398 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=payschedules.delete'); ?>",
3399 {
3400 bid: payschedule.idorder,
3401 schedule_id: payschedule.id,
3402 },
3403 (new_pay_schedules) => {
3404 // dismiss the modal
3405 VBOCore.emitEvent('vbo-eorder-payschedule-logs-dismiss');
3406 // populate the new schedule buttons
3407 let new_pay_schedule_btns = [];
3408 // push button to toggle automatic payment collection scheduling for all bookings
3409 new_pay_schedule_btns.push(vbo_payschedule_btns[0]);
3410 // push button to add a new schedule
3411 new_pay_schedule_btns.push(vbo_payschedule_btns[1]);
3412 // push all active schedules
3413 new_pay_schedules.forEach((payschedule) => {
3414 new_pay_schedule_btns.push(
3415 vboBuildPayScheduleBtn(payschedule)
3416 );
3417 });
3418 // update trigger button class
3419 if (new_pay_schedules.length) {
3420 jQuery('.vbo-context-menu-payschedules').removeClass('btn-primary').addClass('btn-success');
3421 } else {
3422 jQuery('.vbo-context-menu-payschedules').removeClass('btn-success').addClass('btn-primary');
3423 }
3424 // set new buttons in context menu
3425 jQuery('.vbo-context-menu-payschedules').vboContextMenu('buttons', new_pay_schedule_btns);
3426 },
3427 (error) => {
3428 // display error message
3429 alert(error.responseText);
3430 }
3431 );
3432 }
3433 });
3434
3435 // display modal
3436 let modal_body = VBOCore.displayModal({
3437 suffix: 'vbo-pay-schedule-logs',
3438 extra_class: 'vbo-modal-rounded vbo-modal-dialog',
3439 title: payschedule.fordt,
3440 body: '<pre>' + payschedule.logs + '</pre>',
3441 footer_left: footer_left,
3442 footer_right: footer_right,
3443 draggable: true,
3444 dismiss_event: 'vbo-eorder-payschedule-logs-dismiss',
3445 });
3446 }
3447 },
3448 };
3449 }
3450
3451 // build context menu
3452 jQuery(function() {
3453
3454 // append active payment schedule buttons
3455 let active_payschedules = <?php echo json_encode($active_payschedules); ?>;
3456 active_payschedules.forEach((payschedule) => {
3457 vbo_payschedule_btns.push(
3458 vboBuildPayScheduleBtn(payschedule)
3459 );
3460 });
3461
3462 // render context menu
3463 jQuery('.vbo-context-menu-payschedules').vboContextMenu({
3464 placement: 'bottom-left',
3465 buttons: vbo_payschedule_btns,
3466 });
3467
3468 });
3469 </script>
3470 <?php
3471 }
3472 // end automatic payment schedules
3473 }
3474 }
3475 } elseif (empty($row['idorderota']) && !empty($row['paymentlog']) && $row['status'] == 'standby') {
3476 ?>
3477 <div class="vbo-eorder-emptyccdata">
3478 <a class="btn btn-warning" href="index.php?option=com_vikbooking&task=editorder&cid[]=<?php echo $row['id']; ?>&unset_cc=1" onclick="return confirm(Joomla.JText._('VBDELCONFIRM'));"><?php VikBookingIcons::e('broom'); ?> <?php echo JText::translate('VBO_EMPTY_DATA'); ?></a>
3479 </div>
3480 <?php
3481 }
3482
3483 /**
3484 * Attempt to display the reporting invalid credit card layout from VCM.
3485 *
3486 * @requires VCM >= 1.8.27
3487 *
3488 * @since 1.16.9 (J) - 1.6.9 (WP)
3489 */
3490 try {
3491 // prepare the layout data array
3492 $layout_data = [
3493 'caller' => 'vikbooking',
3494 'booking' => $row,
3495 ];
3496
3497 ?>
3498 <div class="vbo-eorder-vcm-reporting-invalidcc">
3499 <?php
3500 // render the reporting-invalidcc layout
3501 echo JLayoutHelper::render('reporting.invalidcc', $layout_data, null, [
3502 'component' => 'com_vikchannelmanager',
3503 'client' => 'admin',
3504 ]);
3505 ?>
3506 </div>
3507 <?php
3508 } catch(Throwable $e) {
3509 // do nothing
3510 }
3511
3512 ?>
3513 </div>
3514 <?php
3515
3516 if (!$cc_acl_denied) {
3517 ?>
3518 <pre><?php echo htmlspecialchars($row['paymentlog']); ?></pre>
3519 <?php
3520 }
3521 ?>
3522 </div>
3523
3524 <script type="text/javascript">
3525 if (window.location.hash == '#paymentlog') {
3526 setTimeout(function() {
3527 jQuery(".vbo-bookingdet-tab[data-vbotab='vbo-tab-admin']").trigger('click');
3528 vbToggleLog(document.getElementById('vbo-trig-paylogs'));
3529 }, 500);
3530 }
3531 </script>
3532 <?php
3533 }
3534 if (!$printreceipt && !is_null($messaging)) {
3535 ?>
3536 <div id="vbmessagingdiv" class="vbo-extra-panel" style="display: none;">
3537 <?php echo $messaging->renderChat(); ?>
3538 </div>
3539 <script type="text/javascript">
3540 jQuery(function() {
3541 if (window.location.hash == '#messaging') {
3542 setTimeout(function() {
3543 jQuery(".vbo-bookingdet-tab[data-vbotab='vbo-tab-admin']").trigger('click');
3544 vbToggleMessaging(document.getElementById('vbo-trig-messaging'));
3545 }, 100);
3546 }
3547 });
3548 </script>
3549 <?php
3550 }
3551
3552 foreach ($adminPanelForms as $legend => $form)
3553 {
3554 $legendId = preg_replace("/[^a-zA-Z0-9_\-]+/", '', $legend);
3555 ?>
3556 <div class="vbo-extra-panel" id="vboextrapanel-<?php echo $legendId; ?>" style="display: none;">
3557 <?php echo $form; ?>
3558 </div>
3559 <?php
3560 }
3561 ?>
3562 </div>
3563 </div>
3564 </div>
3565 </div>
3566
3567 <input type="hidden" name="task" value="editorder">
3568 <input type="hidden" name="vbo_active_tab" id="vbo_active_tab" value="">
3569 <input type="hidden" name="whereup" value="<?php echo $row['id']; ?>">
3570 <input type="hidden" name="cid[]" value="<?php echo $row['id']; ?>">
3571 <input type="hidden" name="option" value="com_vikbooking">
3572 <?php
3573 $tmpl = VikRequest::getVar('tmpl');
3574 if ($tmpl == 'component') {
3575 echo '<input type="hidden" name="tmpl" value="component" />';
3576 }
3577 $pgoto = VikRequest::getString('goto', '', 'request');
3578 if (in_array($pgoto, ['overv', 'ratesoverv'])) {
3579 echo '<input type="hidden" name="goto" value="' . $pgoto . '" />';
3580 }
3581 ?>
3582 </form>
3583 </div>
3584 <?php
3585 foreach ($vbo_modals_html as $modalhtml) {
3586 echo $modalhtml;
3587 }
3588 ?>
3589 <form action="index.php?option=com_vikbooking&amp;task=orders" method="post" id="vbo-gen-invoice">
3590 <input type="hidden" name="option" value="com_vikbooking" />
3591 <input type="hidden" name="task" value="orders" />
3592 <input type="hidden" name="cid[]" value="<?php echo $row['id']; ?>" />
3593 <input type="hidden" name="invnotes" id="invnotes-hid" value="" />
3594 </form>
3595
3596 <div class="vbo-editorder-sms-email-send-helper" style="display: none;">
3597
3598 <div class="vbo-editorder-sms-send-wrap">
3599 <form action="index.php?option=com_vikbooking" method="post" id="vbo-modal-form-sms">
3600 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
3601 <div class="vbo-params-wrap">
3602 <div class="vbo-params-container">
3603
3604 <div class="vbo-param-container vbo-param-container-full">
3605 <div class="vbo-param-label">
3606 <label for="smscont"><?php echo JText::translate('VBSENDSMSCUSTCONT'); ?></label>
3607 </div>
3608 <div class="vbo-param-setting">
3609 <textarea name="smscont" id="smscont" style="width: 99%; min-width: 99%; max-width: 99%; height: 120px;"></textarea>
3610 </div>
3611 </div>
3612
3613 </div>
3614 </div>
3615 </div>
3616 <input type="hidden" name="phone" id="smstophone" value="<?php echo $row['phone']; ?>" />
3617 <input type="hidden" name="goto" value="<?php echo urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id']); ?>" />
3618 <input type="hidden" name="task" value="sendcustomsms" />
3619 </form>
3620 </div>
3621
3622 <div class="vbo-editorder-email-send-wrap">
3623 <form action="index.php?option=com_vikbooking" method="post" enctype="multipart/form-data" id="vbo-modal-form-email">
3624 <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact">
3625 <div class="vbo-params-wrap">
3626 <div class="vbo-params-container">
3627
3628 <?php
3629 $cur_emtpl = VBOFactory::getConfig()->getArray('customemailtpls', []);
3630 if ($cur_emtpl) {
3631 ?>
3632 <div class="vbo-param-container">
3633 <div class="vbo-param-setting">
3634 <select id="emtpl-customemail" onchange="vboLoadEmailTpl(this.value);">
3635 <option value=""><?php echo JText::translate('VBEMAILCUSTFROMTPL'); ?></option>
3636 <?php
3637 foreach ($cur_emtpl as $emk => $emv) {
3638 ?>
3639 <optgroup label="<?php echo $emv['emailsubj']; ?>">
3640 <option value="<?php echo $emk; ?>"><?php echo JText::translate('VBEMAILCUSTFROMTPLUSE'); ?></option>
3641 <option value="rm<?php echo $emk; ?>"><?php echo JText::translate('VBEMAILCUSTFROMTPLRM'); ?></option>
3642 </optgroup>
3643 <?php
3644 }
3645 ?>
3646 </select>
3647 </div>
3648 </div>
3649 <?php
3650 }
3651
3652 /**
3653 * Load all conditional text special tags.
3654 *
3655 * @since 1.14 (J) - 1.4.0 (WP)
3656 */
3657 $extra_btns = [];
3658 $condtext_tags = VikBooking::getConditionalRulesInstance()->getSpecialTags();
3659 if ($condtext_tags) {
3660 $condtext_tags = array_keys($condtext_tags);
3661 foreach ($condtext_tags as $tag) {
3662 array_push($extra_btns, '<button type="button" class="btn btn-secondary btn-small vbo-condtext-specialtag-btn" onclick="setSpecialTplTag(\'emailcont\', \'' . $tag . '\');">' . $tag . '</button>');
3663 }
3664 }
3665 ?>
3666 <div class="vbo-param-container vbo-param-container-full">
3667 <div class="vbo-param-label">
3668 <label for="emailsubj"><?php echo JText::translate('VBSENDEMAILCUSTSUBJ'); ?></label>
3669 </div>
3670 <div class="vbo-param-setting">
3671 <input type="text" name="emailsubj" id="emailsubj" value="" size="30" />
3672 </div>
3673 </div>
3674
3675 <div class="vbo-param-container vbo-param-container-full">
3676 <div class="vbo-param-label">
3677 <label for="emailcont"><?php echo JText::translate('VBSENDEMAILCUSTCONT'); ?></label>
3678 </div>
3679 <div class="vbo-param-setting">
3680 <?php
3681 $special_tags_base = [
3682 '{customer_name}',
3683 '{booking_id}',
3684 '{checkin_date}',
3685 '{checkout_date}',
3686 '{num_nights}',
3687 '{rooms_booked}',
3688 '{rooms_names}',
3689 '{tot_adults}',
3690 '{tot_children}',
3691 '{tot_guests}',
3692 '{total}',
3693 '{total_paid}',
3694 '{remaining_balance}',
3695 '{booking_link}',
3696 ];
3697
3698 $special_tags_base_html = '';
3699 foreach ($special_tags_base as $sp_tag) {
3700 $special_tags_base_html .= '<button type="button" class="btn btn-secondary btn-small" onclick="setSpecialTplTag(\'emailcont\', \'' . $sp_tag . '\');">' . $sp_tag . '</button>' . "\n";
3701 }
3702
3703 /**
3704 * Use the rich text editor (visual editor) to build custom email messages.
3705 *
3706 * @since 1.15.0 (J) - 1.5.0 (WP)
3707 */
3708 $tarea_attr = [
3709 'id' => 'emailcont',
3710 'rows' => '7',
3711 'cols' => '170',
3712 'style' => 'width: 99%; min-width: 99%; max-width: 99%; height: 120px; margin-bottom: 1px;',
3713 ];
3714 $editor_opts = [
3715 'modes' => [
3716 'visual',
3717 'text',
3718 ],
3719 'gen_ai' => [
3720 'booking' => $row,
3721 'customer' => $customer,
3722 'environment' => 'booking',
3723 ],
3724 ];
3725 $editor_btns = $special_tags_base;
3726 if ($condtext_tags) {
3727 $editor_btns = array_merge($editor_btns, $condtext_tags);
3728 }
3729
3730 /**
3731 * Trigger event to allow third-party plugins to add custom special tags.
3732 *
3733 * @since 1.16.10 (J) - 1.6.10 (WP)
3734 */
3735 $custom_btns = VBOFactory::getPlatform()->getDispatcher()->filter('onRenderCustomEmailSpecialTags', [$row, $editor_btns]);
3736 foreach ($custom_btns as $custom_btn) {
3737 // merge custom buttons
3738 $editor_btns = array_merge($editor_btns, (array) $custom_btn);
3739 }
3740
3741 // make sure to filter empty buttons
3742 $editor_btns = array_filter($editor_btns);
3743
3744 // render visual editor
3745 echo $vbo_app->renderVisualEditor('emailcont', '', $tarea_attr, $editor_opts, $editor_btns);
3746 ?>
3747 <div class="btn-group pull-left vbo-smstpl-bgroup vbo-custmail-bgroup vik-contentbuilder-textmode-sptags">
3748 <?php echo $special_tags_base_html . "\n" . implode("\n", $extra_btns); ?>
3749 </div>
3750 </div>
3751 </div>
3752
3753 <div class="vbo-param-container vbo-param-container-full">
3754 <div class="vbo-param-label">
3755 <label for="emailattch"><?php echo JText::translate('VBSENDEMAILCUSTATTCH'); ?></label>
3756 </div>
3757 <div class="vbo-param-setting">
3758 <input type="file" name="emailattch" id="emailattch" />
3759 </div>
3760 </div>
3761
3762 <div class="vbo-param-container vbo-param-container-full">
3763 <div class="vbo-param-label">
3764 <label for="emailfrom"><?php echo JText::translate('VBSENDEMAILCUSTFROM'); ?></label>
3765 </div>
3766 <div class="vbo-param-setting">
3767 <input type="text" name="emailfrom" id="emailfrom" value="<?php echo VikBooking::getSenderMail(); ?>" size="30" />
3768 </div>
3769 </div>
3770
3771 </div>
3772 </div>
3773 </div>
3774 <input type="hidden" name="bid" value="<?php echo $row['id']; ?>" />
3775 <input type="hidden" name="email" id="emailto" value="<?php echo $row['custmail']; ?>" />
3776 <input type="hidden" name="goto" value="<?php echo urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id']); ?>" />
3777 <input type="hidden" name="task" value="sendcustomemail" />
3778 </form>
3779 </div>
3780
3781 <div id="vbo-modal-footer-sms" style="display: none;">
3782 <button type="submit" class="btn vbo-config-btn" onclick="document.getElementById('vbo-modal-form-sms').submit();"><?php VikBookingIcons::e('comment'); ?> <?php echo JText::translate('VBSENDSMSACTION'); ?></button>
3783 </div>
3784 <div id="vbo-modal-footer-email" style="display: none;">
3785 <button type="submit" class="btn vbo-config-btn" onclick="document.getElementById('vbo-modal-form-email').submit();"><?php VikBookingIcons::e('envelope'); ?> <?php echo JText::translate('VBSENDEMAILACTION'); ?></button>
3786 </div>
3787 </div>
3788
3789 <script type="text/javascript">
3790 var vbo_print_only = false;
3791 if (typeof jQuery.fn.tooltip === 'function') {
3792 jQuery(".hasTooltip").tooltip();
3793 }
3794 function vboDisplaySendSMS() {
3795 var cur_phone = jQuery("#smstophone").val();
3796 var phone_set = jQuery("#custphone").trigger('vboupdatephonenumber').val();
3797 if (phone_set.length && phone_set != cur_phone) {
3798 jQuery("#smstophone").val(phone_set);
3799 }
3800
3801 // define the modal cancel button
3802 let cancel_btn = jQuery('<button></button>')
3803 .attr('type', 'button')
3804 .addClass('btn')
3805 .text(Joomla.JText._('VBANNULLA'))
3806 .on('click', function() {
3807 VBOCore.emitEvent('vbo-editorder-send-sms-dismiss');
3808 });
3809
3810 // display modal for email/sms contents
3811 let modal_body = VBOCore.displayModal({
3812 suffix: 'editorder-send-sms',
3813 extra_class: 'vbo-modal-large',
3814 lock_scroll: true,
3815 title: Joomla.JText._('VBSENDSMSACTION') + ': ' + (phone_set && phone_set != cur_phone ? phone_set : cur_phone),
3816 footer_left: cancel_btn,
3817 footer_right: jQuery('#vbo-modal-footer-sms').find('button').clone(),
3818 loading_event: 'vbo-editorder-send-sms-loading',
3819 dismiss_event: 'vbo-editorder-send-sms-dismiss',
3820 onDismiss: () => {
3821 jQuery('.vbo-editorder-sms-send-wrap').appendTo('.vbo-editorder-sms-email-send-helper');
3822 },
3823 });
3824
3825 jQuery('.vbo-editorder-sms-send-wrap').appendTo(modal_body);
3826 }
3827 function vboDisplaySendEmail() {
3828 var cur_email = jQuery("#emailto").val();
3829 var email_set = jQuery("#custmail").val();
3830 if (email_set.length && email_set != cur_email) {
3831 jQuery("#emailto").val(email_set);
3832 }
3833
3834 // define the modal cancel button
3835 let cancel_btn = jQuery('<button></button>')
3836 .attr('type', 'button')
3837 .addClass('btn')
3838 .text(Joomla.JText._('VBANNULLA'))
3839 .on('click', function() {
3840 VBOCore.emitEvent('vbo-editorder-send-email-dismiss');
3841 });
3842
3843 // display modal for email/sms contents
3844 let modal_body = VBOCore.displayModal({
3845 suffix: 'editorder-send-email',
3846 extra_class: 'vbo-modal-large',
3847 lock_scroll: true,
3848 title: Joomla.JText._('VBSENDEMAILACTION') + ': ' + (email_set && email_set != cur_email ? email_set : cur_email),
3849 footer_left: cancel_btn,
3850 footer_right: jQuery('#vbo-modal-footer-email').find('button').clone(),
3851 loading_event: 'vbo-editorder-send-email-loading',
3852 dismiss_event: 'vbo-editorder-send-email-dismiss',
3853 onDismiss: () => {
3854 jQuery('.vbo-editorder-email-send-wrap').appendTo('.vbo-editorder-sms-email-send-helper');
3855 },
3856 });
3857
3858 jQuery('.vbo-editorder-email-send-wrap').appendTo(modal_body);
3859 }
3860 function vboKeyupEmail(event) {
3861 if (event.key && event.key == 'Enter') {
3862 event.preventDefault();
3863 document.adminForm.submit();
3864 return;
3865 }
3866 jQuery('.vbo-bookingdet-save-email').show();
3867 }
3868 function setSpecialTplTag(taid, tpltag) {
3869 var tplobj = document.getElementById(taid);
3870 if (tplobj != null) {
3871 var start = tplobj.selectionStart;
3872 var end = tplobj.selectionEnd;
3873 tplobj.value = tplobj.value.substring(0, start) + tpltag + tplobj.value.substring(end);
3874 tplobj.selectionStart = tplobj.selectionEnd = start + tpltag.length;
3875 tplobj.focus();
3876 }
3877 }
3878 jQuery(function() {
3879 // register to the event emitted when a new payment is made through the virtual terminal widget
3880 document.addEventListener('vbo_new_payment_transaction', (e) => {
3881 if (!e || !e.detail || !e.detail.hasOwnProperty('tn') || !e.detail['tn']) {
3882 // do nothing
3883 return;
3884 }
3885 // reload the page to display the updated information
3886 location.reload();
3887 });
3888 // register to the event emitted when a booking is modified through an admin widget
3889 document.addEventListener('vbo_booking_modified', (e) => {
3890 if (!e || !e.detail || !e.detail.hasOwnProperty('bid') || !e.detail['bid']) {
3891 // do nothing
3892 return;
3893 }
3894 // reload the page to display the new information about the booking just modified
3895 location.reload();
3896 });
3897 // remove overbooking flag
3898 jQuery('.vbo-label-overbooking').on('click', function() {
3899 if (confirm(Joomla.JText._('VBO_CONF_RM_OVERBOOKING_FLAG'))) {
3900 VBOCore.doAjax(
3901 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.delete_type_flag'); ?>",
3902 {
3903 bid: '<?php echo $row['id']; ?>',
3904 flag: 'overbooking',
3905 },
3906 (success) => {
3907 // remove "overbooking" label
3908 let parent_label = jQuery('.vbo-bookdet-container').find('.vbo-label-overbooking').parent('.label');
3909 jQuery('.vbo-bookdet-container').find('.vbo-label-overbooking').remove();
3910 parent_label.text(parent_label.text().replace(' / ', ''));
3911 },
3912 (error) => {
3913 alert(error.responseText);
3914 }
3915 );
3916 }
3917 });
3918 // sessionStorage for current tab
3919 if (typeof sessionStorage !== 'undefined' && !window.location.hash && <?php echo $printreceipt ? 'false' : 'true'; ?>) {
3920 var curtab = sessionStorage.getItem('vboEditOrderTab<?php echo $row['id']; ?>');
3921
3922 setTimeout(() => {
3923 let link = jQuery('.vbo-bookingdet-noteslogs-btn[data-id="' + curtab + '"] a');
3924
3925 if (link.length) {
3926 jQuery(".vbo-bookingdet-tab[data-vbotab='vbo-tab-admin']").trigger('click');
3927 link.trigger('click');
3928 }
3929 }, 128);
3930 }
3931 if (window.location.hash == '#tab-admin') {
3932 setTimeout(function() {
3933 jQuery(".vbo-bookingdet-tab[data-vbotab='vbo-tab-admin']").trigger('click');
3934 }, 100);
3935 }
3936 // Search customer - Start
3937 var vbocustsdelay = (function() {
3938 var timer = 0;
3939 return function(callback, ms) {
3940 clearTimeout(timer);
3941 timer = setTimeout(callback, ms);
3942 };
3943 })();
3944 function vboCustomerSearch(words) {
3945 jQuery("#vbo-searchcust-res").hide().html("");
3946 jQuery("#vbo-searchcust-loading").show();
3947 var jqxhr = jQuery.ajax({
3948 type: "POST",
3949 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=searchcustomer'); ?>",
3950 data: {
3951 kw: words,
3952 tmpl: "component"
3953 }
3954 }).done(function(cont) {
3955 if (cont) {
3956 var obj_res = typeof cont === 'string' ? JSON.parse(cont) : cont;
3957 customers_search_vals = obj_res[0];
3958 jQuery("#vbo-searchcust-res").html(obj_res[1]);
3959 } else {
3960 customers_search_vals = "";
3961 jQuery("#vbo-searchcust-res").html("----");
3962 }
3963 jQuery("#vbo-searchcust-res").show();
3964 jQuery("#vbo-searchcust-loading").hide();
3965 }).fail(function() {
3966 jQuery("#vbo-searchcust-loading").hide();
3967 alert("Error Searching.");
3968 });
3969 }
3970 jQuery("#vbo-searchcust").keyup(function(event) {
3971 vbocustsdelay(function() {
3972 var keywords = jQuery("#vbo-searchcust").val();
3973 var chars = keywords.length;
3974 if (chars > 1) {
3975 if ((event.which > 96 && event.which < 123) || (event.which > 64 && event.which < 91) || event.which == 13) {
3976 vboCustomerSearch(keywords);
3977 }
3978 } else {
3979 if (jQuery("#vbo-searchcust-res").is(":visible")) {
3980 jQuery("#vbo-searchcust-res").hide();
3981 }
3982 }
3983 }, 600);
3984 });
3985 jQuery("body").on("click", ".vbo-custsearchres-entry", function() {
3986 var custid = jQuery(this).attr("data-custid");
3987 if (confirm('<?php echo addslashes(JText::translate('VBOASSIGNNEWCUSTCONF')); ?>')) {
3988 jQuery('#newcustid').val(custid);
3989 document.adminForm.submit();
3990 return;
3991 }
3992 });
3993 // Search customer - End
3994 jQuery(".vbo-bookingdet-tab").click(function() {
3995 var newtabrel = jQuery(this).attr('data-vbotab');
3996 var oldtabrel = jQuery(".vbo-bookingdet-tab-active").attr('data-vbotab');
3997 if (newtabrel == oldtabrel) {
3998 return;
3999 }
4000 if (newtabrel == 'vbo-tab-details' && typeof sessionStorage !== 'undefined') {
4001 sessionStorage.setItem('vboEditOrderTab<?php echo $row['id']; ?>', 'details');
4002 }
4003 jQuery(".vbo-bookingdet-tab").removeClass("vbo-bookingdet-tab-active");
4004 jQuery(this).addClass("vbo-bookingdet-tab-active");
4005 jQuery("#"+oldtabrel).hide();
4006 jQuery("#"+newtabrel).fadeIn();
4007 jQuery("#vbo_active_tab").val(newtabrel);
4008 });
4009 jQuery(".vbo-bookingdet-tab[data-vbotab='<?php echo $pactive_tab; ?>']").trigger('click');
4010 // edit amount paid
4011 jQuery('#vbo-amountpaid-edit').click(function() {
4012 jQuery('#vbo-amountpaid-cont').hide();
4013 jQuery('#vbo-amountpaid-modcont').show();
4014 jQuery('input[name="newamountpaid"]').prop('disabled', false);
4015 if (jQuery('input[name="newamountrefunded"]').length) {
4016 jQuery('input[name="newamountrefunded"]').val('');
4017 }
4018 });
4019 jQuery('#vbo-amountpaid-cancedit').click(function() {
4020 jQuery('#vbo-amountpaid-modcont').hide();
4021 jQuery('#vbo-amountpaid-cont').show();
4022 });
4023 // edit amount refunded
4024 jQuery('#vbo-amountrefunded-edit').click(function() {
4025 jQuery('#vbo-amountrefunded-cont').hide();
4026 jQuery('#vbo-amountrefunded-modcont').show();
4027 jQuery('input[name="newamountrefunded"]').prop('disabled', false);
4028 if (jQuery('input[name="newamountpaid"]').length) {
4029 jQuery('input[name="newamountpaid"]').val('');
4030 }
4031 });
4032 jQuery('#vbo-amountrefunded-cancedit').click(function() {
4033 jQuery('#vbo-amountrefunded-modcont').hide();
4034 jQuery('#vbo-amountrefunded-cont').show();
4035 });
4036 // edit amount payable
4037 jQuery('#vbo-amountpayable-edit').click(function() {
4038 jQuery('#vbo-amountpayable-cont').hide();
4039 jQuery('#vbo-amountpayable-modcont').show();
4040 jQuery('input[name="newamountpayable"]').prop('disabled', false);
4041 });
4042 jQuery('#vbo-amountpayable-cancedit').click(function() {
4043 jQuery('#vbo-amountpayable-modcont').hide();
4044 jQuery('#vbo-amountpayable-cont').show();
4045 });
4046 // edit cancellation fee
4047 jQuery('#vbo-cancfee-edit').click(function() {
4048 jQuery('#vbo-cancfee-cont').hide();
4049 jQuery('#vbo-cancfee-modcont').show();
4050 jQuery('input[name="newcancfee"]').prop('disabled', false);
4051 });
4052 jQuery('#vbo-cancfee-cancedit').click(function() {
4053 jQuery('#vbo-cancfee-modcont').hide();
4054 jQuery('#vbo-cancfee-cont').show();
4055 });
4056 // chat listener
4057 if (typeof VCMChat !== 'undefined') {
4058 jQuery(window).on('chatsync', function(e) {
4059 if (!jQuery("#vcm-chat-audio-notification").length) {
4060 jQuery("body").append("<audio id=\"vcm-audio-notification\" preload=\"auto\"><source type=\"audio/mp3\" src=\"<?php echo VCM_ADMIN_URI; ?>assets/css/audio/new_chat_message.mp3\"></source></audio>");
4061 }
4062 try {
4063 var promise = document.getElementById('vcm-audio-notification').play();
4064 console.log(promise);
4065 } catch (err) {
4066 console.warn('Could not play sound', err);
4067 }
4068 });
4069 }
4070
4071 // zoom-able avatars
4072 jQuery('.vbo-customer-info-box-avatar').each(function() {
4073 var img = jQuery(this).find('img');
4074 if (!img.length) {
4075 return;
4076 }
4077 // register click listener
4078 img.on('click', function(e) {
4079 // stop events propagation
4080 e.preventDefault();
4081 e.stopPropagation();
4082
4083 // check for caption
4084 var caption = jQuery(this).attr('data-caption');
4085
4086 // build modal content
4087 var zoom_modal = jQuery('<div></div>').addClass('vbo-modal-overlay-block vbo-modal-overlay-zoom-image').css('display', 'block');
4088 var zoom_dismiss = jQuery('<a></a>').addClass('vbo-modal-overlay-close');
4089 zoom_dismiss.on('click', function() {
4090 jQuery('.vbo-modal-overlay-zoom-image').fadeOut();
4091 });
4092 zoom_modal.append(zoom_dismiss);
4093 var zoom_content = jQuery('<div></div>').addClass('vbo-modal-overlay-content vbo-modal-overlay-content-zoom-image');
4094 var zoom_head = jQuery('<div></div>').addClass('vbo-modal-overlay-content-head');
4095 var zoom_head_title = jQuery('<span></span>');
4096 if (caption) {
4097 zoom_head_title.text(caption);
4098 }
4099 var zoom_head_close = jQuery('<span></span>').addClass('vbo-modal-overlay-close-times').html('&times;');
4100 zoom_head_close.on('click', function() {
4101 jQuery('.vbo-modal-overlay-zoom-image').fadeOut();
4102 });
4103 zoom_head.append(zoom_head_title).append(zoom_head_close);
4104 var zoom_body = jQuery('<div></div>').addClass('vbo-modal-overlay-content-body vbo-modal-overlay-content-body-scroll');
4105 var zoom_image = jQuery('<div></div>').addClass('vbo-modal-zoom-image-wrap');
4106 zoom_image.append(jQuery(this).clone());
4107 zoom_body.append(zoom_image);
4108 zoom_content.append(zoom_head).append(zoom_body);
4109 zoom_modal.append(zoom_content);
4110 // append modal to body
4111 if (jQuery('.vbo-modal-overlay-zoom-image').length) {
4112 jQuery('.vbo-modal-overlay-zoom-image').remove();
4113 }
4114 jQuery('body').append(zoom_modal);
4115 });
4116 });
4117
4118 // emit the event to read all notifications in the current context
4119 VBOCore.emitEvent('vbo-nc-read-notifications', {
4120 criteria: {
4121 group: '<?php echo !empty($row['idorderota']) && !empty($row['channel']) ? 'otas' : 'website'; ?>',
4122 idorder: '<?php echo $row['id']; ?>',
4123 }
4124 });
4125
4126 // register click event on the booking task(s)
4127 document.querySelectorAll('.vbo-bookingdet-task-details[data-task-id]').forEach((task) => {
4128 const taskId = task.getAttribute('data-task-id');
4129 task.addEventListener('click', (e) => {
4130 e.stopPropagation();
4131 // define the modal cancel button
4132 let cancel_btn = jQuery('<button></button>')
4133 .attr('type', 'button')
4134 .addClass('btn')
4135 .text(Joomla.JText._('VBOCLOSE'))
4136 .on('click', () => {
4137 VBOCore.emitEvent('vbo-tm-edittask-dismiss');
4138 });
4139
4140 // define the modal save button
4141 let save_btn = jQuery('<button></button>')
4142 .attr('type', 'button')
4143 .addClass('btn btn-success')
4144 .text(Joomla.JText._('VBSAVE'))
4145 .on('click', function() {
4146 // disable button to prevent double submissions
4147 let submit_btn = jQuery(this);
4148 submit_btn.prop('disabled', true);
4149
4150 // start loading animation
4151 VBOCore.emitEvent('vbo-tm-edittask-loading');
4152
4153 // get form data
4154 const taskForm = new FormData(document.querySelector('#vbo-tm-task-manage-form'));
4155
4156 // build query parameters for the request
4157 let qpRequest = new URLSearchParams(taskForm);
4158
4159 // make sure the request always includes the assignees query parameter, even if the list is empty
4160 if (!qpRequest.has('data[assignees][]')) {
4161 qpRequest.append('data[assignees][]', []);
4162 }
4163
4164 // make sure the request always includes the tags query parameter, even if the list is empty
4165 if (!qpRequest.has('data[tags][]')) {
4166 qpRequest.append('data[tags][]', []);
4167 }
4168
4169 // make the request
4170 VBOCore.doAjax(
4171 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.updateTask'); ?>",
4172 qpRequest.toString(),
4173 (resp) => {
4174 // dismiss the modal on success
4175 VBOCore.emitEvent('vbo-tm-edittask-dismiss');
4176
4177 // reload the page
4178 location.reload();
4179 },
4180 (error) => {
4181 // display error message
4182 alert(error.responseText);
4183
4184 // re-enable submit button
4185 submit_btn.prop('disabled', false);
4186
4187 // stop loading
4188 VBOCore.emitEvent('vbo-tm-edittask-loading');
4189 }
4190 );
4191 });
4192
4193 // display modal
4194 let modalBody = VBOCore.displayModal({
4195 suffix: 'tm_edittask_modal',
4196 title: <?php echo json_encode(JText::translate('VBO_TASK')); ?> + ' #' + taskId,
4197 extra_class: 'vbo-modal-rounded vbo-modal-taller vbo-modal-large',
4198 body_prepend: true,
4199 lock_scroll: true,
4200 escape_dismiss: false,
4201 footer_left: cancel_btn,
4202 footer_right: save_btn,
4203 loading_event: 'vbo-tm-edittask-loading',
4204 dismiss_event: 'vbo-tm-edittask-dismiss',
4205 });
4206
4207 // start loading animation
4208 VBOCore.emitEvent('vbo-tm-edittask-loading');
4209
4210 // make the request
4211 VBOCore.doAjax(
4212 "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>",
4213 {
4214 type: 'tasks.managetask',
4215 data: {
4216 task_id: taskId,
4217 form_id: 'vbo-tm-task-manage-form',
4218 },
4219 },
4220 (resp) => {
4221 // stop loading
4222 VBOCore.emitEvent('vbo-tm-edittask-loading');
4223
4224 try {
4225 // decode the response (if needed), and append the content to the modal body
4226 let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp;
4227 modalBody.append(obj_res['html']);
4228 } catch (err) {
4229 console.error('Error decoding the response', err, resp);
4230 }
4231 },
4232 (error) => {
4233 // display error message
4234 alert(error.responseText);
4235
4236 // stop loading
4237 VBOCore.emitEvent('vbo-tm-edittask-loading');
4238 }
4239 );
4240 });
4241 });
4242
4243 // register click event to copy the OTA booking ID
4244 const otaBidEl = document.querySelector('.vbo-reservation-copy-otabid');
4245 if (otaBidEl) {
4246 otaBidEl.addEventListener('click', () => {
4247 let copyEl = document.querySelector('textarea.vbo-textarea-copyable[data-copy="otabid"]');
4248 VBOCore.copyToClipboard(copyEl).then((success) => {
4249 otaBidEl.setAttribute('data-tooltiptext', <?php echo json_encode(JText::translate('VBO_COPIED') . '!'); ?>);
4250 }).catch((err) => {
4251 // do nothing
4252 });
4253 });
4254 }
4255
4256 });
4257 var cur_emtpl = <?php echo json_encode($cur_emtpl); ?>;
4258 function vboLoadEmailTpl(tplind) {
4259 if (!(tplind.length > 0)) {
4260 jQuery('#emailsubj').val('');
4261 jQuery('#emailcont').val('').trigger('change');
4262 return true;
4263 }
4264 if (tplind.substr(0, 2) == 'rm') {
4265 if (confirm(Joomla.JText._('VBDELCONFIRM'))) {
4266 document.location.href = 'index.php?option=com_vikbooking&task=rmcustomemailtpl&cid[]=<?php echo $row['id']; ?>&tplind='+tplind.substr(2);
4267 }
4268 return false;
4269 }
4270 if (!cur_emtpl.hasOwnProperty(tplind)) {
4271 jQuery('#emailsubj').val('');
4272 jQuery('#emailcont').val('').trigger('change');
4273 return true;
4274 }
4275 jQuery('#emailsubj').val(cur_emtpl[tplind]['emailsubj']);
4276 jQuery('#emailcont').val(cur_emtpl[tplind]['emailcont']).trigger('change');
4277 jQuery('#emailfrom').val(cur_emtpl[tplind]['emailfrom']);
4278 return true;
4279 }
4280 <?php
4281 $pcustomemail = VikRequest::getInt('customemail', '', 'request');
4282 if ($pcustomemail > 0) {
4283 ?>
4284 vboDisplaySendEmail();
4285 <?php
4286 }
4287 if ($printreceipt) {
4288 ?>
4289 jQuery(function() {
4290 jQuery('button, .vbo-bookingdet-innertop').hide();
4291 jQuery('body').find('a').each(function(k, v) {
4292 jQuery(this).replaceWith(jQuery(this).html());
4293 });
4294 jQuery('body').find("input[type='text']").each(function(k, v) {
4295 jQuery(this).replaceWith(jQuery(this).val());
4296 });
4297 });
4298 function vboMakePrintOnly() {
4299 vbo_print_only = true;
4300 jQuery(".vbo-receipt-numdate-block").remove();
4301 jQuery("#vbo-receipt-print-btn-name").text("<?php echo addslashes(JText::translate('VBOPRINT')); ?>");
4302 }
4303 function vboLaunchPrintReceipt() {
4304 var rcnotes = jQuery('#vbo-receipt-notes').val();
4305 var rnewnum = jQuery('#vbo-receipt-num-inp').val();
4306 if (rcnotes.length) {
4307 if (rcnotes.indexOf('<') < 0) {
4308 rcnotes = rcnotes.replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1<br />$2');
4309 }
4310 jQuery('#vbo-receipt-notes-val').html(rcnotes);
4311 } else {
4312 jQuery('.vbo-receipt-notes-container').remove();
4313 }
4314 if (vbo_print_only === true) {
4315 window.print();
4316 return;
4317 }
4318 jQuery.ajax({
4319 type: "POST",
4320 url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=updatereceiptnum'); ?>",
4321 data: {
4322 newnum: rnewnum,
4323 newnotes: rcnotes,
4324 oid: "<?php echo $row['id']; ?>"
4325 }
4326 }).done(function(res) {
4327 window.print();
4328 }).fail(function() {
4329 alert('Could not update the next receipt number.')
4330 window.print();
4331 });
4332 }
4333 <?php
4334 }
4335 ?>
4336 </script>
4337