| @@ -15,8 +15,10 @@ | ||
| 15 | 15 | $busy = $this->busy; |
| 16 | 16 | $customer = $this->customer; |
| 17 | 17 | $payments = $this->payments; |
| 18 | 18 | |
| 19 | +// load registry and history | |
| 20 | +$registry = VBOBookingRegistry::getInstance($this->row, $this->rooms); | |
| 19 | 21 | $history_obj = VikBooking::getBookingHistoryInstance($row['id']); |
| 20 | 22 | |
| 21 | 23 | // availability helper |
| 22 | 24 | $av_helper = VikBooking::getAvailabilityInstance(); |
| @@ -31,14 +33,29 @@ | ||
| 31 | 33 | JText::script('VBDELCONFIRM'); |
| 32 | 34 | JText::script('VBSENDCANCORDEMAIL'); |
| 33 | 35 | JText::script('VBO_SET_STANDBY'); |
| 34 | 36 | JText::script('VBO_CONF_RM_OVERBOOKING_FLAG'); |
| 37 | +JText::script('VBO_NEW_PAYSCHEDULE'); | |
| 38 | +JText::script('VBANNULLA'); | |
| 39 | +JText::script('VBOCLOSE'); | |
| 40 | +JText::script('VBSAVE'); | |
| 41 | +JText::script('VBELIMINA'); | |
| 42 | +JText::script('VBO_REG_NEW_PAYMENT'); | |
| 43 | +JText::script('VBO_UPDATE_PAYMENT'); | |
| 44 | +JText::script('VBSENDSMSACTION'); | |
| 45 | +JText::script('VBSENDEMAILACTION'); | |
| 46 | +JText::script('VBO_AI_AUTO_GUEST_REV_EXCLUDE'); | |
| 47 | +JText::script('VBO_AI_AUTO_GUEST_REV_INCLUDE'); | |
| 35 | 48 | |
| 36 | 49 | $dbo = JFactory::getDbo(); |
| 37 | 50 | |
| 38 | 51 | $vbo_app = VikBooking::getVboApplication(); |
| 39 | 52 | $vbo_app->loadVisualEditorAssets(); |
| 53 | +$vbo_app->prepareJavaScriptCurrency(); | |
| 40 | 54 | |
| 55 | +// preload chat assets | |
| 56 | +VBOFactory::getChatMediator()->useAssets(); | |
| 57 | + | |
| 41 | 58 | /** |
| 42 | 59 | * This View can render within a modal the "bookingcheckin" View, and with WP |
| 43 | 60 | * this is loaded via AJAX. In order to not interfere or reset the contextual menu, |
| 44 | 61 | * we load the assets from the parent View. Context menu may also be used in this View. |
| @@ -53,8 +70,14 @@ | ||
| 53 | 70 | |
| 54 | 71 | $canDo = JFactory::getUser(); |
| 55 | 72 | $vbo_auth_bookings = $canDo->authorise('core.vbo.bookings', 'com_vikbooking'); |
| 56 | 73 | |
| 74 | +// check if automatic payment collection is enabled for all bookings | |
| 75 | +$automatic_payment_collection = VBOFactory::getConfig()->getBool('auto_payment_collection', false); | |
| 76 | + | |
| 77 | +$booking_has_damage_dep = 0; | |
| 78 | +$current_ts = time(); | |
| 79 | +$ota_type_data = !empty($row['ota_type_data']) ? ((array) json_decode($row['ota_type_data'], true)) : []; | |
| 57 | 80 | $currencyname = VikBooking::getCurrencyName(); |
| 58 | 81 | $currencysymb = VikBooking::getCurrencySymb(); |
| 59 | 82 | $after_tax = VikBooking::ivaInclusa(); |
| 60 | 83 | $nowdf = VikBooking::getDateFormat(true); |
| @@ -134,8 +157,9 @@ | ||
| 134 | 157 | $daysdiff = ceil($daysdiff); |
| 135 | 158 | } |
| 136 | 159 | } |
| 137 | 160 | } |
| 161 | + | |
| 138 | 162 | $otachannel = ''; |
| 139 | 163 | $otachannel_name = ''; |
| 140 | 164 | $otachannel_bid = ''; |
| 141 | 165 | $otacurrency = ''; |
| @@ -147,11 +171,23 @@ | ||
| 147 | 171 | if (strstr($otachannel, '.') !== false) { |
| 148 | 172 | $otaccparts = explode('.', $otachannel); |
| 149 | 173 | $otachannel = $otaccparts[0]; |
| 150 | 174 | } |
| 151 | - $otacurrency = strlen($row['chcurrency']) > 0 ? $row['chcurrency'] : ''; | |
| 175 | + $otacurrency = strlen((string) $row['chcurrency']) > 0 ? $row['chcurrency'] : ''; | |
| 152 | 176 | } |
| 153 | 177 | |
| 178 | +/** | |
| 179 | + * Tell whether the current reservation has or may have a CC/VCC available. | |
| 180 | + */ | |
| 181 | +$may_have_cc_details = false; | |
| 182 | +if (!empty($row['paymentlog']) && stripos($row['paymentlog'], 'card number') !== false && strpos($row['paymentlog'], '****') !== false) { | |
| 183 | + // turn flag on for partial card details available | |
| 184 | + $may_have_cc_details = true; | |
| 185 | +} elseif (!empty($row['channel']) && !strcasecmp($otachannel_name, 'Booking.com')) { | |
| 186 | + // the CM may be able to retrieve the CC details via API | |
| 187 | + $may_have_cc_details = true; | |
| 188 | +} | |
| 189 | + | |
| 154 | 190 | $status_type = ''; |
| 155 | 191 | if (!empty($row['type'])) { |
| 156 | 192 | $status_type = JText::translate('VBO_BTYPE_' . strtoupper($row['type'])); |
| 157 | 193 | if (!strcasecmp($row['type'], 'overbooking')) { |
| @@ -181,8 +217,24 @@ | ||
| 181 | 217 | |
| 182 | 218 | // extend administration sidebar |
| 183 | 219 | $adminSidebarForms = $this->onDisplayView('AdministrationSidebar'); |
| 184 | 220 | |
| 221 | +/** | |
| 222 | + * Check if messaging accounts have been configured through the E4jConnect Channel Manager. | |
| 223 | + * If some messaging API accounts have been configured, SMS fallback will no longer be displayed. | |
| 224 | + * | |
| 225 | + * @since 1.18.8 (J) - 1.8.8 (WP) | |
| 226 | + */ | |
| 227 | +$messagingAccountConfigurations = []; | |
| 228 | +if (class_exists('VCMMessagingAccountsModel')) { | |
| 229 | + $messagingAccountConfigurations = VCMMessagingAccountsModel::getInstance()->getConfigurationsData( | |
| 230 | + new VCMMessagingTemplateDecoratorBooking($registry), | |
| 231 | + [ | |
| 232 | + 'listings' => $registry->getBookedListingIds(), | |
| 233 | + ] | |
| 234 | + ); | |
| 235 | +} | |
| 236 | + | |
| 185 | 237 | //Prepare modal (used for the Registration and for reconstructing the credit card details through the channel manager) |
| 186 | 238 | echo $vbo_app->getJmodalScript(); |
| 187 | 239 | //end Prepare modal |
| 188 | 240 | ?> |
| @@ -312,9 +364,9 @@ | ||
| 312 | 364 | <span><?php echo date(str_replace("/", $datesep, $df).' H:i', $row['ts']); ?></span> |
| 313 | 365 | </div> |
| 314 | 366 | </div> |
| 315 | 367 | <?php |
| 316 | - if (!$printreceipt && count($customer)) { | |
| 368 | + if (!$printreceipt && $customer) { | |
| 317 | 369 | ?> |
| 318 | 370 | <div class="vbo-bookdet-wrap"> |
| 319 | 371 | <div class="vbo-bookdet-head"> |
| 320 | 372 | <span><?php echo JText::translate('VBCUSTOMERNOMINATIVE'); ?></span> |
| @@ -417,9 +469,9 @@ | ||
| 417 | 469 | $checked_btn = 'btn-warning'; |
| 418 | 470 | break; |
| 419 | 471 | default: |
| 420 | 472 | $checked_status = JText::translate('VBOCHECKEDSTATUSZERO'); |
| 421 | - if (count($customer) && isset($customer['pax_data']) && !empty($customer['pax_data'])) { | |
| 473 | + if ($customer && isset($customer['pax_data']) && !empty($customer['pax_data'])) { | |
| 422 | 474 | // pre check-in performed via front-end |
| 423 | 475 | $checked_status = JText::translate('VBOCHECKEDSTATUSPRECHECKIN'); |
| 424 | 476 | } |
| 425 | 477 | break; |
| @@ -441,23 +493,48 @@ | ||
| 441 | 493 | //end Prepare modal |
| 442 | 494 | } |
| 443 | 495 | |
| 444 | 496 | /** |
| 445 | - * Check whether the booking can be refunded. | |
| 497 | + * Check whether the booking can be refunded or charged through an off-session capturing. | |
| 446 | 498 | * |
| 447 | 499 | * @since 1.14 (J) - 1.4.0 (WP) |
| 500 | + * @since 1.18.0 (J) - 1.8.0 (WP) added support to off-session capturing. | |
| 448 | 501 | */ |
| 449 | 502 | |
| 450 | - // refundable up to 7 days after check-out day | |
| 503 | + // refundable/capturable up to 7 days after check-out day | |
| 451 | 504 | $max_refund_ts = mktime(23, 59, 59, $checkout_info['mon'], ($checkout_info['mday'] + 7), $checkout_info['year']); |
| 505 | + | |
| 452 | 506 | // current payment driver must be set |
| 453 | 507 | $tn_driver = is_array($payment) ? $payment['file'] : null; |
| 508 | + | |
| 454 | 509 | // transaction data validation callback |
| 455 | 510 | $tn_data_callback = function($data) use ($tn_driver) { |
| 456 | 511 | return (is_object($data) && isset($data->driver) && basename($data->driver, '.php') == basename($tn_driver, '.php')); |
| 457 | 512 | }; |
| 458 | 513 | $prev_tn_data = $history_obj->getEventsWithData(array('P0', 'PN'), $tn_data_callback); |
| 459 | - $refundable = ($row['status'] != 'standby' && $max_refund_ts >= time() && is_array($prev_tn_data) && count($prev_tn_data)); | |
| 514 | + | |
| 515 | + // whether it's refundable/capturable | |
| 516 | + $refundable = ($row['status'] != 'standby' && !empty($row['totpaid']) && $max_refund_ts >= $current_ts && is_array($prev_tn_data) && $prev_tn_data); | |
| 517 | + $off_session_capturing = ($row['status'] != 'standby' && $max_refund_ts >= $current_ts && is_array($prev_tn_data) && array_filter($prev_tn_data, function($data) { | |
| 518 | + return is_object($data) && ($data->future_usage ?? null); | |
| 519 | + })); | |
| 520 | + | |
| 521 | + if ($off_session_capturing) { | |
| 522 | + ?> | |
| 523 | + <div class="vbo-bookdet-wrap"> | |
| 524 | + <div class="vbo-bookdet-head"> | |
| 525 | + <span><?php echo JText::translate('VBO_CREDIT_CARD'); ?></span> | |
| 526 | + </div> | |
| 527 | + <div class="vbo-bookdet-foot"> | |
| 528 | + <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']; ?>});"> | |
| 529 | + <?php VikBookingIcons::e('credit-card'); ?> | |
| 530 | + <?php echo JText::translate('VBO_W_VIRTUALTERMINAL_TITLE'); ?> | |
| 531 | + </button> | |
| 532 | + </div> | |
| 533 | + </div> | |
| 534 | + <?php | |
| 535 | + } | |
| 536 | + | |
| 460 | 537 | if ($refundable) { |
| 461 | 538 | // prepare modal (refundtn) with a custom function to trigger the opening |
| 462 | 539 | array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-refund-tn', JText::translate('VBO_ISSUE_REFUND'))); |
| 463 | 540 | echo $vbo_app->getJmodalScript('Refund', 'vboDetectRefundChanges();'); |
| @@ -478,9 +555,9 @@ | ||
| 478 | 555 | <div class="vbo-bookdet-head"> |
| 479 | 556 | <span><?php echo JText::translate('VBO_ISSUE_REFUND'); ?></span> |
| 480 | 557 | </div> |
| 481 | 558 | <div class="vbo-bookdet-foot"> |
| 482 | - <button type="button" class="btn btn-small btn-danger vbo-dorefund-btn"<?php echo count($refunds) ? ' data-totrefunds="' . count($refunds) . '"' : ''; ?> onclick="vboOpenJModalRefund('vbo-refund-tn', 'index.php?option=com_vikbooking&task=refundtn&cid[]=<?php echo $row['id']; ?>&tmpl=component');"> | |
| 559 | + <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');"> | |
| 483 | 560 | <?php echo JText::translate('VBO_REFUND'); ?> |
| 484 | 561 | </button> |
| 485 | 562 | </div> |
| 486 | 563 | </div> |
| @@ -485,9 +562,8 @@ | ||
| 485 | 562 | </div> |
| 486 | 563 | </div> |
| 487 | 564 | <?php |
| 488 | 565 | } |
| 489 | - // | |
| 490 | 566 | |
| 491 | 567 | if (!$printreceipt && !empty($row['channel'])) { |
| 492 | 568 | $ota_logo_img = VikBooking::getVcmChannelsLogo($row['channel']); |
| 493 | 569 | if ($ota_logo_img === false) { |
| @@ -586,9 +662,9 @@ | ||
| 586 | 662 | </div> |
| 587 | 663 | </div> |
| 588 | 664 | <?php |
| 589 | 665 | } |
| 590 | - if (!empty($row['channel']) && stripos($row['channel'], 'booking.com') !== false && $row['checkin'] <= time() && strtotime('+ 7 days', $row['checkout']) >= time()) { | |
| 666 | + if (!empty($row['channel']) && stripos($row['channel'], 'booking.com') !== false && $row['checkin'] <= $current_ts && strtotime('+ 7 days', $row['checkout']) >= $current_ts) { | |
| 591 | 667 | /** |
| 592 | 668 | * Guest misconduct reporting API for Booking.com. |
| 593 | 669 | * Only after reservation check-in date and no later than 7 days after check-out date. |
| 594 | 670 | * |
| @@ -662,9 +738,9 @@ | ||
| 662 | 738 | }, |
| 663 | 739 | (res) => { |
| 664 | 740 | // parse the JSON response that contains the categories object with all fields for the reporting |
| 665 | 741 | try { |
| 666 | - var misconduct_fields_rs = JSON.parse(res); | |
| 742 | + var misconduct_fields_rs = typeof res === 'string' ? JSON.parse(res) : res; | |
| 667 | 743 | |
| 668 | 744 | // make sure the request was successful |
| 669 | 745 | if (!misconduct_fields_rs.status) { |
| 670 | 746 | alert(misconduct_fields_rs.error); |
| @@ -849,9 +925,9 @@ | ||
| 849 | 925 | url: "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikchannelmanager&task=submit_bcom_guestmisconduct'); ?>", |
| 850 | 926 | data: submit_fields |
| 851 | 927 | }).done(function(res) { |
| 852 | 928 | try { |
| 853 | - var misconduct_rs = JSON.parse(res); | |
| 929 | + var misconduct_rs = typeof res === 'string' ? JSON.parse(res) : res; | |
| 854 | 930 | console.log(submit_fields, misconduct_rs); |
| 855 | 931 | |
| 856 | 932 | // make sure the request was successful |
| 857 | 933 | if (!misconduct_rs.status) { |
| @@ -980,9 +1056,9 @@ | ||
| 980 | 1056 | $ir_data_callback = function($data) { |
| 981 | 1057 | return (is_object($data) && !empty($data->av_type)); |
| 982 | 1058 | }; |
| 983 | 1059 | $prev_ir_data = $history_obj->getEventsWithData('IR', $ir_data_callback, true); |
| 984 | - if (is_array($prev_ir_data) && count($prev_ir_data)) { | |
| 1060 | + if (is_array($prev_ir_data) && $prev_ir_data) { | |
| 985 | 1061 | // display a message about the availability type at the time of creation of the inquiry reservation |
| 986 | 1062 | |
| 987 | 1063 | // parse original stay dates into DateTime objects |
| 988 | 1064 | $orig_checkin_dt_obj = new JDate($prev_ir_data[0]->checkin_date); |
| @@ -989,9 +1065,9 @@ | ||
| 989 | 1065 | $orig_checkout_dt_obj = new JDate($prev_ir_data[0]->checkout_date); |
| 990 | 1066 | ?> |
| 991 | 1067 | <div class="vbo-bookdet-container vbo-bookdet-inquiry-alert"> |
| 992 | 1068 | <div class="vbo-bookdet-inquiry-alert-dismiss"> |
| 993 | - <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> | |
| 1069 | + <button type="button" class="btn btn-small btn-warning" onclick="jQuery('.vbo-bookdet-inquiry-alert').remove();"><?php VikBookingIcons::e('times-circle'); ?> <?php echo JText::translate('VBOBTNKEEPREMIND'); ?></button> | |
| 994 | 1070 | </div> |
| 995 | 1071 | <div class="vbo-bookdet-inquiry-alert-message"> |
| 996 | 1072 | <div class="vbo-bookdet-inquiry-alert-top"> |
| 997 | 1073 | <span><?php echo JText::translate('VBO_WEB_INQUIRY_ALERT'); ?></span> |
| @@ -1025,8 +1101,43 @@ | ||
| 1025 | 1101 | </div> |
| 1026 | 1102 | <div class="vbo-bookdet-inquiry-alert-bottom"> |
| 1027 | 1103 | <span><?php echo JText::translate('VBO_WEB_INQUIRY_SUGG'); ?></span> |
| 1028 | 1104 | </div> |
| 1105 | + <?php | |
| 1106 | + if (empty($row['idquote'])) { | |
| 1107 | + // even if it cannot be a quote, we make sure it's just an inquiry for now | |
| 1108 | + $createQuoteUri = 'index.php?option=com_vikbooking&view=managequote&' . http_build_query([ | |
| 1109 | + 'customer' => [ | |
| 1110 | + 'id' => $customer['id'] ?? null, | |
| 1111 | + 'first_name' => $customer['first_name'] ?? null, | |
| 1112 | + 'last_name' => $customer['last_name'] ?? null, | |
| 1113 | + 'email' => $customer['email'] ?? null, | |
| 1114 | + 'phone' => $customer['phone'] ?? null, | |
| 1115 | + 'country' => $customer['country'] ?? null, | |
| 1116 | + ], | |
| 1117 | + 'inquiry' => [ | |
| 1118 | + 'checkin' => date('Y-m-d', $row['checkin']), | |
| 1119 | + 'checkout' => date('Y-m-d', $row['checkout']), | |
| 1120 | + 'parties' => array_map(function($or) { | |
| 1121 | + return [ | |
| 1122 | + 'adults' => $or['adults'] ?? 1, | |
| 1123 | + 'children' => $or['children'] ?? 0, | |
| 1124 | + ]; | |
| 1125 | + }, $rooms), | |
| 1126 | + 'rooms' => array_map(function($or) { | |
| 1127 | + return [ | |
| 1128 | + 'id' => $or['idroom'] ?? 0, | |
| 1129 | + ]; | |
| 1130 | + }, $rooms), | |
| 1131 | + ], | |
| 1132 | + ]); | |
| 1133 | + ?> | |
| 1134 | + <div class="vbo-bookdet-inquiry-alert-bottom"> | |
| 1135 | + <a class="btn vbo-config-btn" href="<?php echo VBOFactory::getPlatform()->getUri()->admin($createQuoteUri); ?>"><?php VikBookingIcons::e('file-alt'); ?> <?php echo JText::translate('VBO_CREATE_QUOTE'); ?></a> | |
| 1136 | + </div> | |
| 1137 | + <?php | |
| 1138 | + } | |
| 1139 | + ?> | |
| 1029 | 1140 | </div> |
| 1030 | 1141 | </div> |
| 1031 | 1142 | <?php |
| 1032 | 1143 | } |
| @@ -1042,16 +1153,23 @@ | ||
| 1042 | 1153 | <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> |
| 1043 | 1154 | </div> |
| 1044 | 1155 | <?php |
| 1045 | 1156 | } |
| 1046 | - if ((array_key_exists(1, $tars) && count($tars[1]) > 0) || ($is_package || $is_cust_cost)) { | |
| 1157 | + if (!empty($row['idquote'])) { | |
| 1158 | + ?> | |
| 1159 | + <div class="vbo-bookingdet-command"> | |
| 1160 | + <button class="btn vbo-config-btn vbo-quote-details-btn" type="button"><?php VikBookingIcons::e('file-alt'); ?> <?php echo JText::translate('VBO_QUOTE_DETAILS'); ?></button> | |
| 1161 | + </div> | |
| 1162 | + <?php | |
| 1163 | + } | |
| 1164 | + if ((array_key_exists(1, $tars) && $tars[1]) || ($is_package || $is_cust_cost)) { | |
| 1047 | 1165 | |
| 1048 | 1166 | if (VBOPlatformDetection::isWordPress()) { |
| 1049 | 1167 | /** |
| 1050 | 1168 | * @wponly display warning message if no valid Shortcodes found |
| 1051 | 1169 | */ |
| 1052 | - $model = JModel::getInstance('vikbooking', 'shortcodes'); | |
| 1053 | - $itemid = $model->best('booking'); | |
| 1170 | + $model = JModel::getInstance('vikbooking', 'shortcodes'); | |
| 1171 | + $itemid = $model->best('booking'); | |
| 1054 | 1172 | if (!$itemid) { |
| 1055 | 1173 | VikError::raiseWarning('', 'No Shortcodes found, or no Shortcodes being used in Pages/Posts.'); |
| 1056 | 1174 | } |
| 1057 | 1175 | } |
| @@ -1061,9 +1179,9 @@ | ||
| 1061 | 1179 | <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> |
| 1062 | 1180 | </div> |
| 1063 | 1181 | <?php |
| 1064 | 1182 | } |
| 1065 | - if (($row['status'] == "confirmed" || ($row['status'] == "standby" && !empty($row['custmail']))) && ((array_key_exists(1, $tars) && count($tars[1]) > 0) || ($is_package || $is_cust_cost))) { | |
| 1183 | + if (($row['status'] == "confirmed" || ($row['status'] == "standby" && !empty($row['custmail']))) && ((array_key_exists(1, $tars) && $tars[1]) || ($is_package || $is_cust_cost))) { | |
| 1066 | 1184 | ?> |
| 1067 | 1185 | <div class="vbo-bookingdet-command"> |
| 1068 | 1186 | <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> |
| 1069 | 1187 | </div> |
| @@ -1088,9 +1206,9 @@ | ||
| 1088 | 1206 | </div> |
| 1089 | 1207 | <?php |
| 1090 | 1208 | } |
| 1091 | 1209 | } |
| 1092 | - if ($row['status'] == "standby" || ($row['status'] == "cancelled" && $row['checkout'] >= time())) { | |
| 1210 | + if ($row['status'] == "standby" || ($row['status'] == "cancelled" && $row['checkout'] >= $current_ts)) { | |
| 1093 | 1211 | ?> |
| 1094 | 1212 | <div class="vbo-bookingdet-command"> |
| 1095 | 1213 | <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> |
| 1096 | 1214 | </div> |
| @@ -1099,9 +1217,9 @@ | ||
| 1099 | 1217 | if ($row['status'] == "cancelled" && !$row['closure']) { |
| 1100 | 1218 | ?> |
| 1101 | 1219 | <div class="vbo-bookingdet-command"> |
| 1102 | 1220 | <button type="button" class="btn btn-warning vbo-context-menu-btn vbo-context-menu-actionscanc"> |
| 1103 | - <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBCRONACTIONS'); ?> …</span> | |
| 1221 | + <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBCRONACTIONS'); ?></span> | |
| 1104 | 1222 | <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('sort-down'); ?></span> |
| 1105 | 1223 | </button> |
| 1106 | 1224 | </div> |
| 1107 | 1225 | |
| @@ -1202,11 +1320,84 @@ | ||
| 1202 | 1320 | <div class="vbo-bookingdet-tab" data-vbotab="vbo-tab-admin"><?php echo JText::translate('VBOBOOKDETTABADMIN'); ?></div> |
| 1203 | 1321 | </div> |
| 1204 | 1322 | </div> |
| 1205 | 1323 | |
| 1324 | + <?php | |
| 1325 | + /** | |
| 1326 | + * Check if the booking has got some tasks assigned. | |
| 1327 | + * | |
| 1328 | + * @since 1.18.0 (J) - 1.8.0 (WP) | |
| 1329 | + */ | |
| 1330 | + $taskManager = VBOFactory::getTaskManager(); | |
| 1331 | + $bookingTasks = VBOTaskModelTask::getInstance()->filterItems(['id_order' => $row['id']]); | |
| 1332 | + | |
| 1333 | + /** | |
| 1334 | + * Check if the booking should have had passcodes generated. | |
| 1335 | + * | |
| 1336 | + * @since 1.18.16 (J) - 1.8.16 (WP) | |
| 1337 | + */ | |
| 1338 | + $shouldHavePasscodes = !$history_obj->hasEvent(['ND', 'MD']) && VBOFactory::getDoorAccessControl()->shouldBookingHavePasscodes($registry); | |
| 1339 | + ?> | |
| 1340 | + | |
| 1206 | 1341 | <div class="vbo-bookingdet-tab-cont" id="vbo-tab-details" style="display: block;"> |
| 1207 | 1342 | <div class="vbo-bookingdet-innercontainer"> |
| 1208 | 1343 | <div class="vbo-bookingdet-customer"> |
| 1344 | + <?php | |
| 1345 | + if ($bookingTasks) { | |
| 1346 | + ?> | |
| 1347 | + <div class="vbo-bookingdet-detcont vbo-bookingdet-detcont-tm vbo-hidein-print"> | |
| 1348 | + <div class="vbo-bookingdet-lblcont"> | |
| 1349 | + <label><?php echo JText::translate('VBO_TASK_MANAGER'); ?></label> | |
| 1350 | + </div> | |
| 1351 | + <div class="vbo-bookingdet-inpwrap vbo-bookingdet-tasks-list"> | |
| 1352 | + <?php | |
| 1353 | + foreach ($bookingTasks as $taskRecord) { | |
| 1354 | + $task = VBOTaskTaskregistry::getInstance((array) $taskRecord); | |
| 1355 | + ?> | |
| 1356 | + <div class="vbo-bookingdet-task-details" data-task-id="<?php echo $task->getID(); ?>"> | |
| 1357 | + <div class="vbo-bookingdet-task-detail" data-type="info"> | |
| 1358 | + <span class="vbo-bookingdet-task-title"><?php echo $task->getTitle(); ?></span> | |
| 1359 | + <span class="vbo-bookingdet-task-sub-title"><?php echo $task->getAreaName($task->getAreaID()); ?></span> | |
| 1360 | + </div> | |
| 1361 | + <?php | |
| 1362 | + $taskUnreadMessages = (bool) $task->get('hasUnreadMessages', false); | |
| 1363 | + if ($taskUnreadMessages) { | |
| 1364 | + ?> | |
| 1365 | + <div class="vbo-bookingdet-task-detail" data-type="unread-messages"> | |
| 1366 | + <span class="unread-message-dot"><?php VikBookingIcons::e('comment'); ?></span> | |
| 1367 | + </div> | |
| 1368 | + <?php | |
| 1369 | + } | |
| 1370 | + if ($taskManager->statusTypeExists($task->getStatus())) { | |
| 1371 | + $taskStatus = $taskManager->getStatusTypeInstance($task->getStatus()); | |
| 1372 | + ?> | |
| 1373 | + <div class="vbo-bookingdet-task-detail" data-type="status"> | |
| 1374 | + <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> | |
| 1375 | + </div> | |
| 1376 | + <?php | |
| 1377 | + } | |
| 1378 | + ?> | |
| 1379 | + </div> | |
| 1380 | + <?php | |
| 1381 | + } | |
| 1382 | + ?> | |
| 1383 | + </div> | |
| 1384 | + </div> | |
| 1385 | + <?php | |
| 1386 | + } | |
| 1387 | + if ($shouldHavePasscodes) { | |
| 1388 | + ?> | |
| 1389 | + <div class="vbo-bookingdet-detcont vbo-bookingdet-detcont-dac vbo-hidein-print"> | |
| 1390 | + <div class="vbo-bookingdet-lblcont"> | |
| 1391 | + <label><?php echo JText::translate('VBO_W_DOORACCESSCONTROL_TITLE'); ?></label> | |
| 1392 | + </div> | |
| 1393 | + <div class="vbo-bookingdet-inpwrap vbo-bookingdet-dac-gen"> | |
| 1394 | + <a href="<?php echo VBOFactory::getPlatform()->getUri()->addCSRF('index.php?option=com_vikbooking&task=bookings.generatePasscodes&bid=' . $row['id']); ?>" class="btn"><?php echo JText::translate('VBO_CREATE_PASSCODE'); ?></a> | |
| 1395 | + </div> | |
| 1396 | + </div> | |
| 1397 | + <?php | |
| 1398 | + } | |
| 1399 | + ?> | |
| 1209 | 1400 | <div class="vbo-bookingdet-detcont<?php echo $row['closure'] > 0 ? ' vbo-bookingdet-closure' : ''; ?>"> |
| 1210 | 1401 | <?php |
| 1211 | 1402 | $custdata_parts = explode("\n", $row['custdata']); |
| 1212 | 1403 | if (count($custdata_parts) > 2 && strpos($custdata_parts[0], ':') !== false && strpos($custdata_parts[1], ':') !== false) { |
| @@ -1230,11 +1421,11 @@ | ||
| 1230 | 1421 | } |
| 1231 | 1422 | unset($custdet_parts[0]); |
| 1232 | 1423 | if ((!strcasecmp(trim($custdet_parts[1]), 'http') || !strcasecmp(trim($custdet_parts[1]), 'https')) && !empty($custdet_parts[2]) && strpos($custdet_parts[2], '//') !== false) { |
| 1233 | 1424 | // this is a URI |
| 1234 | - $custd_val = '<a href="' . trim(implode(':', $custdet_parts)) . '" target="_blank"><i class="' . VikBookingIcons::i('external-link') . '"></i></a>'; | |
| 1425 | + $custd_val = '<a href="' . htmlspecialchars(trim(implode(':', $custdet_parts))) . '" target="_blank"><i class="' . VikBookingIcons::i('external-link') . '"></i></a>'; | |
| 1235 | 1426 | } else { |
| 1236 | - $custd_val = trim(implode(':', $custdet_parts)); | |
| 1427 | + $custd_val = htmlspecialchars(trim(implode(':', $custdet_parts))); | |
| 1237 | 1428 | } |
| 1238 | 1429 | } |
| 1239 | 1430 | ?> |
| 1240 | 1431 | <div class="vbo-bookingdet-userdetail"> |
| @@ -1292,13 +1483,20 @@ | ||
| 1292 | 1483 | |
| 1293 | 1484 | </div> |
| 1294 | 1485 | |
| 1295 | 1486 | <?php |
| 1487 | + // build the proper invoice SID for bc | |
| 1488 | + $inv_sid = $row['sid'] ?: $row['idorderota'] ?: ''; | |
| 1489 | + if (empty($row['sid']) && is_file(implode(DIRECTORY_SEPARATOR, [VBO_SITE_PATH, 'helpers', 'invoices', 'generated', "{$row['id']}_{$row['sid']}.pdf"]))) { | |
| 1490 | + // use the old file name signature for OTA bookings | |
| 1491 | + $inv_sid = $row['sid']; | |
| 1492 | + } | |
| 1493 | + | |
| 1296 | 1494 | // build list of invoice details (path/uri & label/button), one by default |
| 1297 | 1495 | $invoice_details = [ |
| 1298 | 1496 | [ |
| 1299 | - 'path' => implode(DIRECTORY_SEPARATOR, [VBO_SITE_PATH, 'helpers', 'invoices', 'generated', "{$row['id']}_{$row['sid']}.pdf"]), | |
| 1300 | - 'uri' => VBO_SITE_URI . 'helpers/invoices/generated/' . "{$row['id']}_{$row['sid']}.pdf", | |
| 1497 | + 'path' => implode(DIRECTORY_SEPARATOR, [VBO_SITE_PATH, 'helpers', 'invoices', 'generated', "{$row['id']}_{$inv_sid}.pdf"]), | |
| 1498 | + 'uri' => VBO_SITE_URI . 'helpers/invoices/generated/' . "{$row['id']}_{$inv_sid}.pdf", | |
| 1301 | 1499 | 'label' => JText::translate('VBOCOLORTAGRULEINVONE'), |
| 1302 | 1500 | 'btn' => JText::translate('VBOINVDOWNLOAD'), |
| 1303 | 1501 | ] |
| 1304 | 1502 | ]; |
| @@ -1328,14 +1526,30 @@ | ||
| 1328 | 1526 | ?> |
| 1329 | 1527 | <div class="vbo-bookingdet-detcont vbo-bookingdet-detcont-labels-wrap vbo-hidein-print"> |
| 1330 | 1528 | <?php |
| 1331 | 1529 | if (!empty($row['channel']) && !empty($row['idorderota'])) { |
| 1530 | + $tiny_logo_url = ''; | |
| 1531 | + $channelparts = explode('_', $row['channel']); | |
| 1532 | + if ($ch_logo = VikBooking::getVcmChannelsLogo($row['channel'], true)) { | |
| 1533 | + $tiny_logo_url = $ch_logo->getTinyLogoURL(); | |
| 1534 | + } | |
| 1535 | + $displayOtaBid = !strcasecmp((string) $row['type'], 'Inquiry') && $row['status'] == 'standby' ? '' : $row['idorderota']; | |
| 1332 | 1536 | ?> |
| 1333 | - <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-idorderota"> | |
| 1537 | + <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-idorderota <?php echo strtolower(preg_replace('/[^a-z0-9]/i', '', $channelparts[0])); ?>"> | |
| 1334 | 1538 | <span class="label label-info"> |
| 1335 | - <span><?php echo $otachannel_name . ' ID'; ?></span> | |
| 1336 | - <span class="badge"><?php echo !strcasecmp((string)$row['type'], 'Inquiry') && $row['status'] == 'standby' ? '-----' : $row['idorderota']; ?></span> | |
| 1539 | + <span class="vbo-bookingdet-ota-details"> | |
| 1540 | + <?php | |
| 1541 | + if ($tiny_logo_url) { | |
| 1542 | + ?> | |
| 1543 | + <span class="vbo-bookingdet-ota-logo"><img src="<?php echo $tiny_logo_url; ?>" /></span> | |
| 1544 | + <?php | |
| 1545 | + } | |
| 1546 | + ?> | |
| 1547 | + <span class="vbo-bookingdet-ota-name"><?php echo $otachannel_name . ' ID'; ?></span> | |
| 1548 | + </span> | |
| 1549 | + <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> | |
| 1337 | 1550 | </span> |
| 1551 | + <textarea class="vbo-textarea-copyable" data-copy="otabid"><?php echo htmlentities($displayOtaBid); ?></textarea> | |
| 1338 | 1552 | </div> |
| 1339 | 1553 | <?php |
| 1340 | 1554 | } |
| 1341 | 1555 | if (strlen((string)$row['confirmnumber'])) { |
| @@ -1347,8 +1561,103 @@ | ||
| 1347 | 1561 | </span> |
| 1348 | 1562 | </div> |
| 1349 | 1563 | <?php |
| 1350 | 1564 | } |
| 1565 | + | |
| 1566 | + /** | |
| 1567 | + * Check for AI automated host-to-guest reviews. | |
| 1568 | + * | |
| 1569 | + * @since 1.16.10 (J) - 1.6.10 (WP) | |
| 1570 | + */ | |
| 1571 | + if (class_exists('VikChannelManager') && VikChannelManager::hostToGuestReviewSupported($row, $willbe = true)) { | |
| 1572 | + if (class_exists('VCMAiModelSettings') && (new VCMAiModelSettings)->isGuestReviewAutoResponderEnabled()) { | |
| 1573 | + // host-to-guest review will be supported and AI auto-guest-review is enabled | |
| 1574 | + $ai_auto_guest_review_opt = (array) VBOFactory::getConfig()->getArray('ai_auto_guest_review_opt_' . $row['id'], []); | |
| 1575 | + ?> | |
| 1576 | + <div class="vbo-bookingdet-detcont-ai-info"> | |
| 1577 | + <p class="vbo-bookingdet-detcont-ai-info-status"> | |
| 1578 | + <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> | |
| 1579 | + <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> | |
| 1580 | + </p> | |
| 1581 | + <button type="button" class="btn btn-small btn-primary vbo-context-menu-btn vbo-context-menu-ai-autoreview"> | |
| 1582 | + <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBCRONACTIONS'); ?></span> | |
| 1583 | + <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('sort-down'); ?></span> | |
| 1584 | + </button> | |
| 1585 | + </div> | |
| 1586 | + | |
| 1587 | + <script type="text/javascript"> | |
| 1588 | + // build context menu | |
| 1589 | + jQuery(function() { | |
| 1590 | + | |
| 1591 | + // toggle ignore AI auto-review guest function | |
| 1592 | + let vbo_action_ignore_ai_autorg = (now_ignore) => { | |
| 1593 | + if (confirm(Joomla.JText._((now_ignore ? 'VBO_AI_AUTO_GUEST_REV_INCLUDE' : 'VBO_AI_AUTO_GUEST_REV_EXCLUDE')))) { | |
| 1594 | + // update the auto-review ignore status for this booking | |
| 1595 | + VBOCore.doAjax( | |
| 1596 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.set_ai_auto_guest_review_opt'); ?>", | |
| 1597 | + { | |
| 1598 | + bid: '<?php echo $row['id']; ?>', | |
| 1599 | + opt: { | |
| 1600 | + ignore: (now_ignore ? 0 : 1), | |
| 1601 | + }, | |
| 1602 | + }, | |
| 1603 | + (opt) => { | |
| 1604 | + // populate the new buttons | |
| 1605 | + let new_auto_review_opt = []; | |
| 1606 | + new_auto_review_opt.push({ | |
| 1607 | + icon: ((opt.ignore || 0) ? '<?php echo VikBookingIcons::i('check-circle'); ?>' : '<?php echo VikBookingIcons::i('ban'); ?>'), | |
| 1608 | + text: Joomla.JText._((opt?.ignore ? 'VBO_AI_AUTO_GUEST_REV_INCLUDE' : 'VBO_AI_AUTO_GUEST_REV_EXCLUDE')), | |
| 1609 | + class: (opt?.ignore ? 'vbo-context-menu-entry-success' : 'vbo-context-menu-entry-danger'), | |
| 1610 | + separator: true, | |
| 1611 | + action: (root, config) => { | |
| 1612 | + // register callback | |
| 1613 | + vbo_action_ignore_ai_autorg(opt.ignore || 0); | |
| 1614 | + }, | |
| 1615 | + }); | |
| 1616 | + | |
| 1617 | + // set new buttons in context menu | |
| 1618 | + jQuery('.vbo-context-menu-ai-autoreview').vboContextMenu('buttons', new_auto_review_opt); | |
| 1619 | + | |
| 1620 | + // display the proper status label | |
| 1621 | + if (opt?.ignore) { | |
| 1622 | + jQuery('.vbo-bookingdet-detcont-ai-info-status-on').hide(); | |
| 1623 | + jQuery('.vbo-bookingdet-detcont-ai-info-status-off').show(); | |
| 1624 | + } else { | |
| 1625 | + jQuery('.vbo-bookingdet-detcont-ai-info-status-off').hide(); | |
| 1626 | + jQuery('.vbo-bookingdet-detcont-ai-info-status-on').show(); | |
| 1627 | + } | |
| 1628 | + }, | |
| 1629 | + (error) => { | |
| 1630 | + // display error message | |
| 1631 | + alert(error.responseText); | |
| 1632 | + } | |
| 1633 | + ); | |
| 1634 | + } | |
| 1635 | + }; | |
| 1636 | + | |
| 1637 | + // render context menu | |
| 1638 | + jQuery('.vbo-context-menu-ai-autoreview').vboContextMenu({ | |
| 1639 | + placement: 'bottom-left', | |
| 1640 | + buttons: [ | |
| 1641 | + { | |
| 1642 | + icon: '<?php echo VikBookingIcons::i(($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'check-circle' : 'ban'); ?>', | |
| 1643 | + text: Joomla.JText._('<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'VBO_AI_AUTO_GUEST_REV_INCLUDE' : 'VBO_AI_AUTO_GUEST_REV_EXCLUDE'; ?>'), | |
| 1644 | + class: '<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0) ? 'vbo-context-menu-entry-success' : 'vbo-context-menu-entry-danger'; ?>', | |
| 1645 | + separator: true, | |
| 1646 | + action: (root, config) => { | |
| 1647 | + // register callback | |
| 1648 | + vbo_action_ignore_ai_autorg(<?php echo ($ai_auto_guest_review_opt['ignore'] ?? 0); ?>); | |
| 1649 | + }, | |
| 1650 | + } | |
| 1651 | + ], | |
| 1652 | + }); | |
| 1653 | + | |
| 1654 | + }); | |
| 1655 | + </script> | |
| 1656 | + <?php | |
| 1657 | + } | |
| 1658 | + } | |
| 1659 | + | |
| 1351 | 1660 | if ($invoiced) { |
| 1352 | 1661 | foreach ($invoice_details as $invoice_detail) { |
| 1353 | 1662 | ?> |
| 1354 | 1663 | <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-invoice"> |
| @@ -1362,10 +1671,10 @@ | ||
| 1362 | 1671 | } |
| 1363 | 1672 | if ($this->vcm_review) { |
| 1364 | 1673 | ?> |
| 1365 | 1674 | <div class="vbo-bookingdet-detcont-label vbo-bookingdet-detcont-label-review"> |
| 1366 | - <span class="label label-warning"> | |
| 1367 | - <a href="index.php?option=com_vikchannelmanager&task=reviews&revid=<?php echo $this->vcm_review['id']; ?>" target="_blank" style="color: #fff;"><i class="vboicn-star-full"></i> <?php echo JText::translate('VBOSEEGUESTREVIEW'); ?></a> | |
| 1675 | + <span class="label label-warning" onclick="VBOCore.handleDisplayWidgetNotification({widget_id: 'guest_reviews'}, {review_id: '<?php echo $this->vcm_review['id']; ?>'});"> | |
| 1676 | + <a href="javascript: void(0);" style="color: #fff;"><i class="vboicn-star-full"></i> <?php echo JText::translate('VBOSEEGUESTREVIEW'); ?></a> | |
| 1368 | 1677 | </span> |
| 1369 | 1678 | </div> |
| 1370 | 1679 | <?php |
| 1371 | 1680 | // check if a notification was clicked |
| @@ -1370,13 +1679,15 @@ | ||
| 1370 | 1679 | <?php |
| 1371 | 1680 | // check if a notification was clicked |
| 1372 | 1681 | if (VikRequest::getString('notif_action', '', 'request') == 'see_guest_review') { |
| 1373 | 1682 | $vcm_review_link = VBOFactory::getPlatform()->getUri()->admin('index.php?option=com_vikchannelmanager&task=reviews&revid=' . $this->vcm_review['id'], false); |
| 1683 | + $vcm_review_id = $this->vcm_review['id']; | |
| 1374 | 1684 | JFactory::getDocument()->addScriptDeclaration( |
| 1375 | 1685 | <<<JS |
| 1376 | 1686 | jQuery(function() { |
| 1377 | 1687 | setTimeout(() => { |
| 1378 | - document.location.href = '$vcm_review_link'; | |
| 1688 | + // document.location.href = '$vcm_review_link'; | |
| 1689 | + VBOCore.handleDisplayWidgetNotification({widget_id: 'guest_reviews'}, {review_id: '$vcm_review_id'}); | |
| 1379 | 1690 | }, 200); |
| 1380 | 1691 | }); |
| 1381 | 1692 | JS |
| 1382 | 1693 | ); |
| @@ -1387,10 +1698,9 @@ | ||
| 1387 | 1698 | <!-- Define role to detect the supported hook --> |
| 1388 | 1699 | <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"invoice","type":"field"} --> |
| 1389 | 1700 | |
| 1390 | 1701 | <?php |
| 1391 | - if (isset($bookingSidebarForms['invoice'])) | |
| 1392 | - { | |
| 1702 | + if (isset($bookingSidebarForms['invoice'])) { | |
| 1393 | 1703 | echo $bookingSidebarForms['invoice']; |
| 1394 | 1704 | } |
| 1395 | 1705 | ?> |
| 1396 | 1706 | |
| @@ -1405,15 +1715,15 @@ | ||
| 1405 | 1715 | </div> |
| 1406 | 1716 | <div class="vbo-bookingdet-inpwrap"> |
| 1407 | 1717 | <div class="vbo-bookingdet-inpcont"> |
| 1408 | 1718 | <input type="text" name="custmail" id="custmail" value="<?php echo $this->escape($row['custmail']); ?>" size="25" onkeyup="vboKeyupEmail(event);"/> |
| 1719 | + <div class="vbo-bookingdet-btncont vbo-bookingdet-save-email" style="display: none;"> | |
| 1720 | + <button type="button" class="btn btn-success" onclick="document.adminForm.submit();"><?php VikBookingIcons::e('save'); ?> <?php echo JText::translate('VBSAVE'); ?></button> | |
| 1721 | + </div> | |
| 1409 | 1722 | </div> |
| 1410 | - <div class="vbo-bookingdet-btncont vbo-bookingdet-save-email" style="display: none;"> | |
| 1411 | - <button type="button" class="btn btn-success" onclick="document.adminForm.submit();"><?php VikBookingIcons::e('save'); ?> <?php echo JText::translate('VBSAVE'); ?></button> | |
| 1412 | - </div> | |
| 1413 | 1723 | <?php if (!empty($row['custmail'])) : ?> |
| 1414 | 1724 | <div class="vbo-bookingdet-btncont"> |
| 1415 | - <button type="button" class="btn vbo-config-btn" onclick="vboToggleSendEmail();" style="vertical-align: top;"><?php VikBookingIcons::e('envelope'); ?> <?php echo JText::translate('VBSENDEMAILACTION'); ?></button> | |
| 1725 | + <button type="button" class="btn vbo-config-btn" onclick="vboDisplaySendEmail();" style="vertical-align: top;"><?php VikBookingIcons::e('envelope'); ?> <?php echo JText::translate('VBSENDEMAILACTION'); ?></button> | |
| 1416 | 1726 | </div> |
| 1417 | 1727 | <?php endif; ?> |
| 1418 | 1728 | </div> |
| 1419 | 1729 | |
| @@ -1420,10 +1730,9 @@ | ||
| 1420 | 1730 | <!-- Define role to detect the supported hook --> |
| 1421 | 1731 | <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"email","type":"field"} --> |
| 1422 | 1732 | |
| 1423 | 1733 | <?php |
| 1424 | - if (isset($bookingSidebarForms['email'])) | |
| 1425 | - { | |
| 1734 | + if (isset($bookingSidebarForms['email'])) { | |
| 1426 | 1735 | echo $bookingSidebarForms['email']; |
| 1427 | 1736 | } |
| 1428 | 1737 | ?> |
| 1429 | 1738 | |
| @@ -1435,13 +1744,27 @@ | ||
| 1435 | 1744 | <div class="vbo-bookingdet-inpwrap"> |
| 1436 | 1745 | <div class="vbo-bookingdet-inpcont"> |
| 1437 | 1746 | <?php echo $vbo_app->printPhoneInputField(array('name' => 'custphone', 'id' => 'custphone', 'value' => $this->escape($row['phone'])), array('nationalMode' => false, 'fullNumberOnBlur' => true)); ?> |
| 1438 | 1747 | </div> |
| 1439 | - <?php if (!empty($row['phone'])) : ?> | |
| 1748 | + <?php | |
| 1749 | + if (!empty($row['phone'])) { | |
| 1750 | + if ($messagingAccountConfigurations) { | |
| 1751 | + // send a message to the guest phone number through the messaging API account(s) configured | |
| 1752 | + ?> | |
| 1440 | 1753 | <div class="vbo-bookingdet-btncont"> |
| 1441 | - <button type="button" class="btn vbo-config-btn" onclick="vboToggleSendSMS();" style="vertical-align: top;"><?php VikBookingIcons::e('comment-dots'); ?> <?php echo JText::translate('VBSENDSMSACTION'); ?></button> | |
| 1754 | + <button type="button" class="btn vbo-config-btn vbo-bookingdet-send-tplmessage-btn" style="vertical-align: top;"><?php VikBookingIcons::e('paper-plane'); ?> <?php echo JText::translate('VBO_SEND_MESSAGE'); ?></button> | |
| 1442 | 1755 | </div> |
| 1443 | - <?php endif; ?> | |
| 1756 | + <?php | |
| 1757 | + } else { | |
| 1758 | + // fallback onto SMS | |
| 1759 | + ?> | |
| 1760 | + <div class="vbo-bookingdet-btncont"> | |
| 1761 | + <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> | |
| 1762 | + </div> | |
| 1763 | + <?php | |
| 1764 | + } | |
| 1765 | + } | |
| 1766 | + ?> | |
| 1444 | 1767 | </div> |
| 1445 | 1768 | |
| 1446 | 1769 | <!-- Define role to detect the supported hook --> |
| 1447 | 1770 | <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"phone","type":"field"} --> |
| @@ -1446,24 +1769,48 @@ | ||
| 1446 | 1769 | <!-- Define role to detect the supported hook --> |
| 1447 | 1770 | <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"phone","type":"field"} --> |
| 1448 | 1771 | |
| 1449 | 1772 | <?php |
| 1450 | - if (isset($bookingSidebarForms['phone'])) | |
| 1451 | - { | |
| 1773 | + if (isset($bookingSidebarForms['phone'])) { | |
| 1452 | 1774 | echo $bookingSidebarForms['phone']; |
| 1453 | 1775 | } |
| 1454 | 1776 | ?> |
| 1455 | 1777 | |
| 1456 | 1778 | </div> |
| 1779 | + <?php | |
| 1780 | + if ($phoneAlias = $registry->getAliasPhoneNumber()) { | |
| 1781 | + ?> | |
| 1782 | + <div class="vbo-bookingdet-detcont vbo-hidein-print"> | |
| 1783 | + <div class="vbo-bookingdet-lblcont"> | |
| 1784 | + <label for="phone_alias"><?php VikBookingIcons::e('user-shield'); ?> <?php echo JText::translate('VBO_PHONE_ALIAS'); ?></label> | |
| 1785 | + </div> | |
| 1786 | + <div class="vbo-bookingdet-inpwrap"> | |
| 1787 | + <div class="vbo-bookingdet-inpcont"> | |
| 1788 | + <input type="text" id="phone_alias" value="<?php echo $this->escape($phoneAlias); ?>" readonly /> | |
| 1789 | + </div> | |
| 1790 | + <span class="vbo-param-setting-comment"><?php echo JText::translate('VBO_PHONE_ALIAS_HELP'); ?></span> | |
| 1791 | + </div> | |
| 1457 | 1792 | |
| 1793 | + <!-- Define role to detect the supported hook --> | |
| 1794 | + <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","key":"phone_alias","type":"field"} --> | |
| 1795 | + | |
| 1796 | + <?php | |
| 1797 | + if (isset($bookingSidebarForms['phone_alias'])) { | |
| 1798 | + echo $bookingSidebarForms['phone_alias']; | |
| 1799 | + } | |
| 1800 | + ?> | |
| 1801 | + | |
| 1802 | + </div> | |
| 1803 | + <?php | |
| 1804 | + } | |
| 1805 | + ?> | |
| 1806 | + | |
| 1458 | 1807 | <!-- Define role to detect the supported hook --> |
| 1459 | 1808 | <!-- {"rule":"customizer","event":"onDisplayViewVikBookingEditorderSidebar","type":"fieldset"} --> |
| 1460 | 1809 | |
| 1461 | 1810 | <?php |
| 1462 | - foreach ($bookingSidebarForms as $legend => $form) | |
| 1463 | - { | |
| 1464 | - if (in_array($legend, ['userdetails', 'invoice', 'email', 'phone'])) | |
| 1465 | - { | |
| 1811 | + foreach ($bookingSidebarForms as $legend => $form) { | |
| 1812 | + if (in_array($legend, ['userdetails', 'invoice', 'email', 'phone'])) { | |
| 1466 | 1813 | // skip default forms |
| 1467 | 1814 | continue; |
| 1468 | 1815 | } |
| 1469 | 1816 | ?> |
| @@ -1513,10 +1860,10 @@ | ||
| 1513 | 1860 | <td class="vbo-bookingdet-summary-room-firstcell"> |
| 1514 | 1861 | <div class="vbo-bookingdet-summary-room-wrap"> |
| 1515 | 1862 | <div class="vbo-bookingdet-summary-roomnum"><?php VikBookingIcons::e($room_icon); ?> <?php echo JText::translate('VBEDITORDERTHREE').' '.$num; ?></div> |
| 1516 | 1863 | <?php |
| 1517 | - //Room Specific Unit | |
| 1518 | - if (!$row['closure'] && $row['status'] == "confirmed" && !empty($or['params'])) { | |
| 1864 | + // Room Specific Unit | |
| 1865 | + if ((!$row['closure'] || ($row['closure'] && count($rooms) === 1) && !empty($or['roomindex'])) && $row['status'] == "confirmed" && !empty($or['params'])) { | |
| 1519 | 1866 | $room_params = json_decode($or['params'], true); |
| 1520 | 1867 | $arr_features = array(); |
| 1521 | 1868 | $unavailable_indexes = VikBooking::getRoomUnitNumsUnavailable($row, $or['idroom']); |
| 1522 | 1869 | if (is_array($room_params) && array_key_exists('features', $room_params) && !empty($room_params['features'])) { |
| @@ -1531,9 +1878,9 @@ | ||
| 1531 | 1878 | } |
| 1532 | 1879 | } |
| 1533 | 1880 | } |
| 1534 | 1881 | } |
| 1535 | - if (count($arr_features)) { | |
| 1882 | + if ($arr_features) { | |
| 1536 | 1883 | // $or['id'] equals to the ID of each matching record in _ordersrooms |
| 1537 | 1884 | ?> |
| 1538 | 1885 | <div class="vbo-bookingdet-summary-roomnum-chunit"> |
| 1539 | 1886 | <?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']] : ''); ?> |
| @@ -1559,9 +1906,9 @@ | ||
| 1559 | 1906 | if ($arrpeople[$num]['children'] > 0) { |
| 1560 | 1907 | $age_str = ''; |
| 1561 | 1908 | if (!empty($arrpeople[$num]['children_age'])) { |
| 1562 | 1909 | $json_child = json_decode($arrpeople[$num]['children_age'], true); |
| 1563 | - if (is_array($json_child) && isset($json_child['age']) && is_array($json_child['age']) && count($json_child['age'])) { | |
| 1910 | + if (is_array($json_child) && isset($json_child['age']) && is_array($json_child['age']) && $json_child['age']) { | |
| 1564 | 1911 | $age_str = ' '.JText::sprintf('VBORDERCHILDAGES', implode(', ', $json_child['age'])); |
| 1565 | 1912 | } |
| 1566 | 1913 | } |
| 1567 | 1914 | ?> |
| @@ -1650,9 +1997,9 @@ | ||
| 1650 | 1997 | </div> |
| 1651 | 1998 | <?php |
| 1652 | 1999 | } |
| 1653 | 2000 | |
| 1654 | - if ($row['split_stay'] && count($room_stay_dates) && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) { | |
| 2001 | + if ($row['split_stay'] && $room_stay_dates && isset($room_stay_dates[$ind]) && $room_stay_dates[$ind]['idroom'] == $or['idroom']) { | |
| 1655 | 2002 | // print split stay information for this room |
| 1656 | 2003 | $room_stay_checkin = !empty($room_stay_dates[$ind]['checkin_ts']) ? $room_stay_dates[$ind]['checkin_ts'] : $room_stay_dates[$ind]['checkin']; |
| 1657 | 2004 | $room_stay_checkout = !empty($room_stay_dates[$ind]['checkout_ts']) ? $room_stay_dates[$ind]['checkout_ts'] : $room_stay_dates[$ind]['checkout']; |
| 1658 | 2005 | $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout); |
| @@ -1664,9 +2011,9 @@ | ||
| 1664 | 2011 | <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> |
| 1665 | 2012 | </div> |
| 1666 | 2013 | </div> |
| 1667 | 2014 | <?php |
| 1668 | - } elseif (!$row['split_stay'] && count($room_stay_records) && isset($room_stay_records[$ind]) && $room_stay_records[$ind]['idroom'] == $or['idroom']) { | |
| 2015 | + } elseif (!$row['split_stay'] && $room_stay_records && isset($room_stay_records[$ind]) && $room_stay_records[$ind]['idroom'] == $or['idroom']) { | |
| 1669 | 2016 | // print modified stay dates information for this room |
| 1670 | 2017 | $room_stay_checkin = $room_stay_records[$ind]['checkin']; |
| 1671 | 2018 | $room_stay_checkout = $room_stay_records[$ind]['checkout']; |
| 1672 | 2019 | $room_stay_nights = $av_helper->countNightsOfStay($room_stay_checkin, $room_stay_checkout); |
| @@ -1712,8 +2059,17 @@ | ||
| 1712 | 2059 | $actopt = $dbo->loadAssocList(); |
| 1713 | 2060 | if (!$actopt) { |
| 1714 | 2061 | continue; |
| 1715 | 2062 | } |
| 2063 | + | |
| 2064 | + // option params | |
| 2065 | + $opt_params = !empty($actopt[0]['oparams']) ? json_decode($actopt[0]['oparams'], true) : []; | |
| 2066 | + $opt_params = is_array($opt_params) ? $opt_params : []; | |
| 2067 | + if ($opt_params['damagedep'] ?? 0) { | |
| 2068 | + // turn flag on | |
| 2069 | + $booking_has_damage_dep = 1; | |
| 2070 | + } | |
| 2071 | + | |
| 1716 | 2072 | $counter++; |
| 1717 | 2073 | $chvar = ''; |
| 1718 | 2074 | if (!empty($actopt[0]['ageintervals']) && $or['children'] > 0 && strstr($stept[1], '-') != false) { |
| 1719 | 2075 | $optagenames = VikBooking::getOptionIntervalsAges($actopt[0]['ageintervals']); |
| @@ -1749,9 +2105,9 @@ | ||
| 1749 | 2105 | } |
| 1750 | 2106 | $actopt[0]['chageintv'] = $chvar; |
| 1751 | 2107 | $actopt[0]['name'] .= ' ('.$optagenames[($chvar - 1)].')'; |
| 1752 | 2108 | $realcost = (intval($actopt[0]['perday']) == 1 ? (floatval($optagecosts[($chvar - 1)]) * $room_stay_nights * $stept[1]) : (floatval($optagecosts[($chvar - 1)]) * $stept[1])); |
| 1753 | - } else { | |
| 2109 | + } elseif (is_numeric($stept[1])) { | |
| 1754 | 2110 | // VBO 1.11 - options percentage cost of the room total fee |
| 1755 | 2111 | if ($is_package === true || (!empty($or['cust_cost']) && $or['cust_cost'] > 0.00)) { |
| 1756 | 2112 | $deftar_basecosts = $or['cust_cost']; |
| 1757 | 2113 | } else { |
| @@ -1760,8 +2116,10 @@ | ||
| 1760 | 2116 | } |
| 1761 | 2117 | $actopt[0]['cost'] = (int)$actopt[0]['pcentroom'] ? ($deftar_basecosts * $actopt[0]['cost'] / 100) : $actopt[0]['cost']; |
| 1762 | 2118 | // |
| 1763 | 2119 | $realcost = (intval($actopt[0]['perday']) == 1 ? ($actopt[0]['cost'] * $room_stay_nights * $stept[1]) : ($actopt[0]['cost'] * $stept[1])); |
| 2120 | + } else { | |
| 2121 | + $realcost = 0; | |
| 1764 | 2122 | } |
| 1765 | 2123 | if ($actopt[0]['maxprice'] > 0 && $realcost > $actopt[0]['maxprice']) { |
| 1766 | 2124 | $realcost = $actopt[0]['maxprice']; |
| 1767 | 2125 | if (intval($actopt[0]['hmany']) == 1 && intval($stept[1]) > 1) { |
| @@ -1768,8 +2126,19 @@ | ||
| 1768 | 2126 | $realcost = $actopt[0]['maxprice'] * $stept[1]; |
| 1769 | 2127 | } |
| 1770 | 2128 | } |
| 1771 | 2129 | $realcost = $actopt[0]['perperson'] == 1 ? ($realcost * $arrpeople[$num]['adults']) : $realcost; |
| 2130 | + | |
| 2131 | + /** | |
| 2132 | + * Trigger event to allow third party plugins to apply a custom calculation for the option/extra fee or tax. | |
| 2133 | + * | |
| 2134 | + * @since 1.17.7 (J) - 1.7.7 (WP) | |
| 2135 | + */ | |
| 2136 | + $custom_calculation = VBOFactory::getPlatform()->getDispatcher()->filter('onCalculateBookingOptionFeeCost', [$realcost, &$actopt[0], $row, $or]); | |
| 2137 | + if ($custom_calculation) { | |
| 2138 | + $realcost = (float) $custom_calculation[0]; | |
| 2139 | + } | |
| 2140 | + | |
| 1772 | 2141 | $tmpopr = VikBooking::sayOptionalsPlusIva($realcost, $actopt[0]['idiva']); |
| 1773 | 2142 | ?> |
| 1774 | 2143 | <tr class="vbo-bookingdet-summary-options"> |
| 1775 | 2144 | <td class="vbo-bookingdet-summary-options-title"><?php echo $counter == 1 ? JText::translate('VBEDITORDEREIGHT') : ' '; ?></td> |
| @@ -1857,9 +2226,9 @@ | ||
| 1857 | 2226 | //Reservation Total |
| 1858 | 2227 | //Taxes Breakdown (only if tot_taxes is greater than 0) |
| 1859 | 2228 | $tax_breakdown = array(); |
| 1860 | 2229 | $base_aliq = 0; |
| 1861 | - if (count($all_id_prices) > 0 && $row['tot_taxes'] > 0) { | |
| 2230 | + if ($all_id_prices && $row['tot_taxes'] > 0) { | |
| 1862 | 2231 | //only last type of price assuming that the tax breakdown is equivalent in case of different rates |
| 1863 | 2232 | $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;"; |
| 1864 | 2233 | $dbo->setQuery($q); |
| 1865 | 2234 | $breakdown_info = $dbo->loadAssoc(); |
| @@ -1865,9 +2234,9 @@ | ||
| 1865 | 2234 | $breakdown_info = $dbo->loadAssoc(); |
| 1866 | 2235 | if ($breakdown_info) { |
| 1867 | 2236 | if (!empty($breakdown_info['breakdown']) && !empty($breakdown_info['aliq'])) { |
| 1868 | 2237 | $tax_breakdown = json_decode($breakdown_info['breakdown'], true); |
| 1869 | - $tax_breakdown = is_array($tax_breakdown) && count($tax_breakdown) > 0 ? $tax_breakdown : array(); | |
| 2238 | + $tax_breakdown = is_array($tax_breakdown) && $tax_breakdown ? $tax_breakdown : array(); | |
| 1870 | 2239 | $base_aliq = $breakdown_info['aliq']; |
| 1871 | 2240 | } |
| 1872 | 2241 | } |
| 1873 | 2242 | } |
| @@ -1908,9 +2277,9 @@ | ||
| 1908 | 2277 | <div class="vbdiscenter-entry"> |
| 1909 | 2278 | <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> |
| 1910 | 2279 | </div> |
| 1911 | 2280 | <?php |
| 1912 | - if (count($tax_breakdown)) { | |
| 2281 | + if ($tax_breakdown) { | |
| 1913 | 2282 | foreach ($tax_breakdown as $tbkk => $tbkv) { |
| 1914 | 2283 | $tax_break_cost = $row['tot_taxes'] * floatval($tbkv['aliq']) / $base_aliq; |
| 1915 | 2284 | ?> |
| 1916 | 2285 | <div class="vbdiscenter-entry vbdiscenter-entry-breakdown"> |
| @@ -1928,9 +2297,19 @@ | ||
| 1928 | 2297 | </div> |
| 1929 | 2298 | <div class="vbdiscenter-entry"> |
| 1930 | 2299 | <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> |
| 1931 | 2300 | </div> |
| 2301 | + <?php | |
| 2302 | + if ($booking_has_damage_dep) { | |
| 2303 | + // allow to overwrite (or see) the amount of damage deposit | |
| 2304 | + ?> | |
| 1932 | 2305 | <div class="vbdiscenter-entry"> |
| 2306 | + <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> | |
| 2307 | + </div> | |
| 2308 | + <?php | |
| 2309 | + } | |
| 2310 | + ?> | |
| 2311 | + <div class="vbdiscenter-entry"> | |
| 1933 | 2312 | <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> |
| 1934 | 2313 | </div> |
| 1935 | 2314 | <div class="vbdiscenter-entrycentered"> |
| 1936 | 2315 | <button type="submit" class="btn btn-success"><?php echo JText::translate('VBAPPLYDISCOUNTSAVE'); ?></button> |
| @@ -1937,9 +2316,26 @@ | ||
| 1937 | 2316 | </div> |
| 1938 | 2317 | </div> |
| 1939 | 2318 | </td> |
| 1940 | 2319 | <td> |
| 1941 | - <span class="vbo-bookingdet-summary-cost"><?php echo (strlen($otacurrency) > 0 ? '('.$otacurrency.') '.$currencyname : $currencyname); ?> <?php echo VikBooking::numberFormat($row['total']); ?></span> | |
| 2320 | + <span class="vbo-bookingdet-summary-cost"><?php echo (!empty($otacurrency) && $otacurrency != $currencyname ? '('.$otacurrency.') ' . $currencyname : $currencyname); ?> <?php echo VikBooking::numberFormat($row['total']); ?></span> | |
| 2321 | + <?php | |
| 2322 | + /** | |
| 2323 | + * Display the information about the expected payout, if available and eligible. | |
| 2324 | + * | |
| 2325 | + * @since 1.18.4 (J) - 1.8.4 (WP) | |
| 2326 | + */ | |
| 2327 | + if ($row['status'] == 'confirmed' && !empty($row['channel']) && !empty($row['idorderota']) && $row['checkout'] >= $current_ts && !empty($ota_type_data['expected_payout'])) { | |
| 2328 | + ?> | |
| 2329 | + <div class="vbo-bookingdet-exp-payout"> | |
| 2330 | + <span class="vbo-bookingdet-exp-payout-lbl"><?php echo JText::translate('VBO_EXPECTED_PAYOUT'); ?></span> | |
| 2331 | + <span class="vbo-bookingdet-exp-payout-txt"><?php | |
| 2332 | + echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($ota_type_data['expected_payout']), (!empty($otacurrency) && $otacurrency != $currencyname ? $otacurrency : $currencysymb)); | |
| 2333 | + ?></span> | |
| 2334 | + </div> | |
| 2335 | + <?php | |
| 2336 | + } | |
| 2337 | + ?> | |
| 1942 | 2338 | </td> |
| 1943 | 2339 | </tr> |
| 1944 | 2340 | <?php |
| 1945 | 2341 | if ($row['total'] > 0 && !$row['closure']) { |
| @@ -1944,8 +2340,12 @@ | ||
| 1944 | 2340 | <?php |
| 1945 | 2341 | if ($row['total'] > 0 && !$row['closure']) { |
| 1946 | 2342 | $has_paid = ($row['totpaid'] > 0); |
| 1947 | 2343 | $diff_to_pay = $has_paid ? ($row['total'] - $row['totpaid']) : 0; |
| 2344 | + if ($diff_to_pay && !empty($row['idorderota']) && !empty($row['channel']) && round($row['cmms'], 2) == round($diff_to_pay, 2)) { | |
| 2345 | + // the outstanding balance is equal to the OTA commissions amount | |
| 2346 | + $diff_to_pay = 0; | |
| 2347 | + } | |
| 1948 | 2348 | if ($has_paid || $row['status'] != 'standby') { |
| 1949 | 2349 | ?> |
| 1950 | 2350 | <tr class="vbo-bookingdet-summary-totpaid"> |
| 1951 | 2351 | <td> </td> |
| @@ -2003,9 +2403,9 @@ | ||
| 2003 | 2403 | </tr> |
| 2004 | 2404 | <?php |
| 2005 | 2405 | } |
| 2006 | 2406 | } |
| 2007 | - if (!$printreceipt && $row['status'] == 'confirmed' && VikBooking::multiplePayments() && is_array($payment) && !empty($payment['id']) && $row['checkout'] > time()) { | |
| 2407 | + if (!$printreceipt && $row['status'] == 'confirmed' && VikBooking::multiplePayments() && is_array($payment) && !empty($payment['id']) && $row['checkout'] > strtotime('-10 days')) { | |
| 2008 | 2408 | /** |
| 2009 | 2409 | * The amount payable can be modified by the admin. |
| 2010 | 2410 | * |
| 2011 | 2411 | * @since 1.14 (J) - 1.4.0 (WP) |
| @@ -2111,9 +2511,9 @@ | ||
| 2111 | 2511 | <?php |
| 2112 | 2512 | if (!$row['closure']) { |
| 2113 | 2513 | ?> |
| 2114 | 2514 | <div class="vbo-bookingdet-admin-entry"> |
| 2115 | - <label for="vbo-searchcust"><?php echo JText::translate(count($customer) ? 'VBOASSIGNNEWCUST' : 'VBFILLCUSTFIELDS'); ?></label> | |
| 2515 | + <label for="vbo-searchcust"><?php echo JText::translate($customer ? 'VBOASSIGNNEWCUST' : 'VBFILLCUSTFIELDS'); ?></label> | |
| 2116 | 2516 | <span style="display: block;"><?php echo JText::translate('VBOSEARCHEXISTCUST'); ?></span> |
| 2117 | 2517 | <span class="vbo-eorder-assigncust" style="margin-bottom: 1px;"> |
| 2118 | 2518 | <input type="text" id="vbo-searchcust" autocomplete="off" value="" placeholder="<?php echo JText::translate('VBOSEARCHCUSTBY'); ?>" size="30" style="margin-bottom: 0;" /> |
| 2119 | 2519 | </span> |
| @@ -2149,11 +2549,11 @@ | ||
| 2149 | 2549 | <?php |
| 2150 | 2550 | } |
| 2151 | 2551 | $chpayment = ''; |
| 2152 | 2552 | if ($payments) { |
| 2153 | - $chpayment = '<div><select name="newpayment" id="newpayment" onchange="changePayment();"><option value="">'.JText::translate('VBCHANGEPAYLABEL').'</option>'; | |
| 2553 | + $chpayment = '<div><select name="newpayment" id="newpayment" onchange="changePayment();"><option value="">- ' . JText::translate('VBCHANGEPAYLABEL') . ' -</option>'; | |
| 2154 | 2554 | foreach ($payments as $pay) { |
| 2155 | - $chpayment .= '<option value="'.$pay['id'].'">'.(is_array($payment) && $payment['id'] == $pay['id'] ? ' ::' : '').$pay['name'].'</option>'; | |
| 2555 | + $chpayment .= '<option value="' . $pay['id'] . '">' . (is_array($payment) && $payment['id'] == $pay['id'] ? '- ' : '') . $pay['name'] . '</option>'; | |
| 2156 | 2556 | } |
| 2157 | 2557 | $chpayment .= '</select></div>'; |
| 2158 | 2558 | } |
| 2159 | 2559 | echo $chpayment; |
| @@ -2246,9 +2646,9 @@ | ||
| 2246 | 2646 | } else { |
| 2247 | 2647 | $channelparts = explode('_', $row['channel']); |
| 2248 | 2648 | // check if this is a meta search channel |
| 2249 | 2649 | $is_meta_search = false; |
| 2250 | - if (preg_match("/(customer).*[0-9]$/", $channelparts[0]) || !strcasecmp($channelparts[0], 'googlehotel') || !strcasecmp($channelparts[0], 'trivago')) { | |
| 2650 | + if (preg_match("/(customer).*[0-9]$/", $channelparts[0]) || !strcasecmp($channelparts[0], 'googlehotel') || !strcasecmp($channelparts[0], 'googlevr') || !strcasecmp($channelparts[0], 'trivago')) { | |
| 2251 | 2651 | $is_meta_search = empty($row['idorderota']); |
| 2252 | 2652 | } |
| 2253 | 2653 | if ($is_meta_search) { |
| 2254 | 2654 | // customer of type sales channel should use front-end reservation chat handler |
| @@ -2343,9 +2743,9 @@ | ||
| 2343 | 2743 | } |
| 2344 | 2744 | |
| 2345 | 2745 | if (!empty($row['paymentlog'])) { |
| 2346 | 2746 | $paylogs_lbl = JText::translate('VBPAYMENTLOGTOGGLE'); |
| 2347 | - if (stripos($row['paymentlog'], 'card number') !== false && strpos($row['paymentlog'], '****') !== false) { | |
| 2747 | + if ($may_have_cc_details) { | |
| 2348 | 2748 | $paylogs_lbl = JText::translate('VBO_CREDIT_CARD'); |
| 2349 | 2749 | } |
| 2350 | 2750 | ?> |
| 2351 | 2751 | <div class="vbo-bookingdet-noteslogs-btn" data-id="paylogs"> |
| @@ -2360,9 +2760,9 @@ | ||
| 2360 | 2760 | ?> |
| 2361 | 2761 | </div> |
| 2362 | 2762 | <div class="vbo-bookingdet-noteslogs-cont"> |
| 2363 | 2763 | <div id="vbadminnotesdiv" class="vbo-extra-panel" style="display: block;"> |
| 2364 | - <textarea name="adminnotes" class="vbadminnotestarea"><?php echo strip_tags((string)$row['adminnotes']); ?></textarea> | |
| 2764 | + <textarea name="adminnotes" class="vbadminnotestarea"><?php echo JHtml::fetch('esc_textarea', (string) $row['adminnotes']); ?></textarea> | |
| 2365 | 2765 | <input type="submit" name="updadmnotes" value="<?php echo JText::translate('VBADMINNOTESUPD'); ?>" class="btn btn-success" /> |
| 2366 | 2766 | </div> |
| 2367 | 2767 | <?php |
| 2368 | 2768 | if ($takings) { |
| @@ -2386,9 +2786,9 @@ | ||
| 2386 | 2786 | foreach (array_reverse($takings) as $hist) { |
| 2387 | 2787 | // calculate amount paid and description |
| 2388 | 2788 | $tn_amount_paid = 0; |
| 2389 | 2789 | $tn_amount_fees = 0; |
| 2390 | - $tn_description = strpos($hist['descr'], '<') !== false ? $hist['descr'] : preg_replace("/\R/", ' - ', $hist['descr']); | |
| 2790 | + $tn_description = strpos((string) $hist['descr'], '<') !== false ? $hist['descr'] : preg_replace("/\R/", ' - ', (string) $hist['descr']); | |
| 2391 | 2791 | if (is_object($hist['data'])) { |
| 2392 | 2792 | // calculate amount paid or amount refunded |
| 2393 | 2793 | if (($hist['data']->amount_paid ?? 0)) { |
| 2394 | 2794 | $tn_amount_paid = $hist['data']->amount_paid; |
| @@ -2419,12 +2819,29 @@ | ||
| 2419 | 2819 | $booking_total_taking += $tn_amount_paid; |
| 2420 | 2820 | $booking_total_prfees += $tn_amount_fees; |
| 2421 | 2821 | ?> |
| 2422 | 2822 | <tr class="vbo-booking-takings-row"> |
| 2423 | - <td><?php echo $currencysymb . ' ' . VikBooking::numberFormat($tn_amount_paid); ?></td> | |
| 2823 | + <td> | |
| 2824 | + <?php | |
| 2825 | + echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($tn_amount_paid), $currencysymb); | |
| 2826 | + if (!strcasecmp($hist['type'], 'PU')) { | |
| 2827 | + /** | |
| 2828 | + * Allow to edit or delete the history record. | |
| 2829 | + * | |
| 2830 | + * @since 1.16.10 (J) - 1.6.10 (WP) | |
| 2831 | + */ | |
| 2832 | + ?> | |
| 2833 | + <div class="vbo-booking-taking-cmds"> | |
| 2834 | + <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> | |
| 2835 | + <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> | |
| 2836 | + </div> | |
| 2837 | + <?php | |
| 2838 | + } | |
| 2839 | + ?> | |
| 2840 | + </td> | |
| 2424 | 2841 | <td><?php echo JHtml::fetch('date', $hist['dt'], 'Y-m-d H:i:s'); ?></td> |
| 2425 | 2842 | <td><?php echo $history_obj->validType($hist['type'], true); ?></td> |
| 2426 | - <td><?php echo $currencysymb . ' ' . VikBooking::numberFormat($tn_amount_fees); ?></td> | |
| 2843 | + <td><?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($tn_amount_fees), $currencysymb); ?></td> | |
| 2427 | 2844 | <td><?php echo $tn_description; ?></td> |
| 2428 | 2845 | </tr> |
| 2429 | 2846 | <?php |
| 2430 | 2847 | } |
| @@ -2432,19 +2849,262 @@ | ||
| 2432 | 2849 | </tbody> |
| 2433 | 2850 | <tfoot> |
| 2434 | 2851 | <tr> |
| 2435 | 2852 | <td colspan="2"> |
| 2436 | - <span><?php echo $currencysymb . ' ' . VikBooking::numberFormat($booking_total_taking); ?></span> | |
| 2853 | + <span><?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($booking_total_taking), $currencysymb); ?></span> | |
| 2437 | 2854 | </td> |
| 2438 | 2855 | <td></td> |
| 2439 | - <td colspan="2"> | |
| 2440 | - <span><?php echo $currencysymb . ' ' . VikBooking::numberFormat($booking_total_prfees); ?></span> | |
| 2856 | + <td> | |
| 2857 | + <span><?php echo VikBooking::formatCurrencyNumber(VikBooking::numberFormat($booking_total_prfees), $currencysymb); ?></span> | |
| 2441 | 2858 | </td> |
| 2859 | + <td> | |
| 2860 | + <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> | |
| 2861 | + </td> | |
| 2442 | 2862 | </tr> |
| 2443 | 2863 | </tfoot> |
| 2444 | 2864 | </table> |
| 2445 | 2865 | </div> |
| 2866 | + | |
| 2867 | + <div class="vbo-eorder-newtaking-helper-wrap" style="display: none;"> | |
| 2868 | + <div class="vbo-eorder-newtaking-helper-cont"> | |
| 2869 | + <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact"> | |
| 2870 | + <div class="vbo-params-wrap"> | |
| 2871 | + <div class="vbo-params-container"> | |
| 2872 | + <div class="vbo-params-block"> | |
| 2873 | + <div class="vbo-param-container"> | |
| 2874 | + <div class="vbo-param-label"> | |
| 2875 | + <label for="new_taking_amount"><?php echo JText::translate('VBO_CC_AMOUNT'); ?></label> | |
| 2876 | + </div> | |
| 2877 | + <div class="vbo-param-setting"> | |
| 2878 | + <div class="vbo-input-currency-wrap"> | |
| 2879 | + <span><?php echo $currencysymb; ?></span> | |
| 2880 | + <input type="number" id="new_taking_amount" value="" min="0" max="<?php echo $row['total']; ?>" step="any" /> | |
| 2881 | + </div> | |
| 2882 | + <span class="vbo-param-setting-comment"> | |
| 2883 | + <?php echo JText::translate('VBOCUSTOMERCMMSONTOTAL') . ' ' . VikBooking::formatCurrencyNumber(VikBooking::numberFormat($row['total']), $currencysymb) . ' - ' . JText::translate('VBAMOUNTPAID') . ' ' . VikBooking::formatCurrencyNumber(VikBooking::numberFormat($row['totpaid']), $currencysymb); ?> | |
| 2884 | + </span> | |
| 2885 | + </div> | |
| 2886 | + </div> | |
| 2887 | + <div class="vbo-param-container"> | |
| 2888 | + <div class="vbo-param-label"> | |
| 2889 | + <label for="new_taking_descr"><?php echo JText::translate('VBLIBPAYNAME'); ?></label> | |
| 2890 | + </div> | |
| 2891 | + <div class="vbo-param-setting"> | |
| 2892 | + <select id="new_taking_payid"> | |
| 2893 | + <option value=""> </option> | |
| 2894 | + <?php | |
| 2895 | + foreach ($this->payments as $paymeth) { | |
| 2896 | + ?> | |
| 2897 | + <option value="<?php echo $paymeth['id']; ?>"><?php echo $paymeth['name']; ?></option> | |
| 2898 | + <?php | |
| 2899 | + } | |
| 2900 | + ?> | |
| 2901 | + </select> | |
| 2902 | + </div> | |
| 2903 | + </div> | |
| 2904 | + <div class="vbo-param-container vbo-param-nested" id="vbo-new-taking-custom-wrap"> | |
| 2905 | + <div class="vbo-param-label"> </div> | |
| 2906 | + <div class="vbo-param-setting"> | |
| 2907 | + <input id="new_taking_descr" type="text" value="" maxlength="200" placeholder="<?php echo $this->escape(JText::translate('VBPVIEWOPTIONALSTWO')); ?>" /> | |
| 2908 | + </div> | |
| 2909 | + </div> | |
| 2910 | + </div> | |
| 2911 | + </div> | |
| 2912 | + </div> | |
| 2913 | + </div> | |
| 2914 | + </div> | |
| 2915 | + </div> | |
| 2916 | + | |
| 2446 | 2917 | </div> |
| 2918 | + | |
| 2919 | + <script type="text/javascript"> | |
| 2920 | + jQuery(function() { | |
| 2921 | + | |
| 2922 | + jQuery('#new_taking_payid').on('change', function() { | |
| 2923 | + if (jQuery(this).val()) { | |
| 2924 | + jQuery('#vbo-new-taking-custom-wrap').hide(); | |
| 2925 | + jQuery('#new_taking_descr').val(''); | |
| 2926 | + } else { | |
| 2927 | + jQuery('#vbo-new-taking-custom-wrap').show(); | |
| 2928 | + } | |
| 2929 | + }); | |
| 2930 | + | |
| 2931 | + jQuery('.vbo-takings-addnew').on('click', function() { | |
| 2932 | + // build modal buttons | |
| 2933 | + let footer_left = jQuery('<button></button>'); | |
| 2934 | + footer_left.addClass('btn'); | |
| 2935 | + footer_left.attr('type', 'button'); | |
| 2936 | + footer_left.text(Joomla.JText._('VBANNULLA')); | |
| 2937 | + footer_left.on('click', function() { | |
| 2938 | + // dismiss the modal | |
| 2939 | + VBOCore.emitEvent('vbo-eorder-new-taking-dismiss'); | |
| 2940 | + }); | |
| 2941 | + | |
| 2942 | + let footer_right = jQuery('<button></button>'); | |
| 2943 | + footer_right.addClass('btn btn-success'); | |
| 2944 | + footer_right.attr('type', 'button'); | |
| 2945 | + footer_right.text(Joomla.JText._('VBSAVE')); | |
| 2946 | + footer_right.on('click', function() { | |
| 2947 | + // disable button to prevent double submissions | |
| 2948 | + let submit_btn = jQuery(this); | |
| 2949 | + submit_btn.prop('disabled', true); | |
| 2950 | + // make the request | |
| 2951 | + VBOCore.doAjax( | |
| 2952 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.add_taking'); ?>", | |
| 2953 | + { | |
| 2954 | + bid: '<?php echo $row['id']; ?>', | |
| 2955 | + amount: jQuery('#new_taking_amount').val(), | |
| 2956 | + payid: jQuery('#new_taking_payid').val(), | |
| 2957 | + descr: jQuery('#new_taking_descr').val(), | |
| 2958 | + }, | |
| 2959 | + (success) => { | |
| 2960 | + // dismiss the modal | |
| 2961 | + VBOCore.emitEvent('vbo-eorder-new-taking-dismiss'); | |
| 2962 | + // reload the page by following the response URL | |
| 2963 | + document.location.href = success.url; | |
| 2964 | + }, | |
| 2965 | + (error) => { | |
| 2966 | + // re-enable submit button | |
| 2967 | + submit_btn.prop('disabled', false); | |
| 2968 | + // display error message | |
| 2969 | + alert(error.responseText); | |
| 2970 | + } | |
| 2971 | + ); | |
| 2972 | + }); | |
| 2973 | + | |
| 2974 | + // display modal | |
| 2975 | + let modal_body = VBOCore.displayModal({ | |
| 2976 | + suffix: 'vbo-new-taking', | |
| 2977 | + extra_class: 'vbo-modal-rounded vbo-modal-dialog', | |
| 2978 | + title: Joomla.JText._('VBO_REG_NEW_PAYMENT'), | |
| 2979 | + body: '', | |
| 2980 | + body_prepend: true, | |
| 2981 | + footer_left: footer_left, | |
| 2982 | + footer_right: footer_right, | |
| 2983 | + draggable: true, | |
| 2984 | + dismiss_event: 'vbo-eorder-new-taking-dismiss', | |
| 2985 | + onDismiss: () => { | |
| 2986 | + jQuery('.vbo-eorder-newtaking-helper-cont').appendTo( | |
| 2987 | + jQuery('.vbo-eorder-newtaking-helper-wrap') | |
| 2988 | + ); | |
| 2989 | + }, | |
| 2990 | + }); | |
| 2991 | + | |
| 2992 | + // reset helper input values | |
| 2993 | + jQuery('#new_taking_amount').val(''); | |
| 2994 | + jQuery('#new_taking_payid').prop('disabled', false).val('').trigger('change'); | |
| 2995 | + jQuery('#new_taking_descr').val(''); | |
| 2996 | + | |
| 2997 | + // append modal body | |
| 2998 | + jQuery('.vbo-eorder-newtaking-helper-cont').appendTo(modal_body); | |
| 2999 | + }); | |
| 3000 | + | |
| 3001 | + jQuery('.vbo-booking-taking-edit').on('click', function() { | |
| 3002 | + let edit_btn = jQuery(this); | |
| 3003 | + let history_id = edit_btn.attr('data-historyid'); | |
| 3004 | + let curr_amount_paid = edit_btn.attr('data-amount'); | |
| 3005 | + let curr_pay_descr = edit_btn.closest('tr.vbo-booking-takings-row').find('td').last().text(); | |
| 3006 | + | |
| 3007 | + // build modal buttons | |
| 3008 | + let footer_left = jQuery('<button></button>'); | |
| 3009 | + footer_left.addClass('btn'); | |
| 3010 | + footer_left.attr('type', 'button'); | |
| 3011 | + footer_left.text(Joomla.JText._('VBANNULLA')); | |
| 3012 | + footer_left.on('click', function() { | |
| 3013 | + // dismiss the modal | |
| 3014 | + VBOCore.emitEvent('vbo-eorder-edit-taking-dismiss'); | |
| 3015 | + }); | |
| 3016 | + | |
| 3017 | + let footer_right = jQuery('<button></button>'); | |
| 3018 | + footer_right.addClass('btn btn-success'); | |
| 3019 | + footer_right.attr('type', 'button'); | |
| 3020 | + footer_right.text(Joomla.JText._('VBO_UPDATE_PAYMENT')); | |
| 3021 | + footer_right.on('click', function() { | |
| 3022 | + // disable button to prevent double submissions | |
| 3023 | + let submit_btn = jQuery(this); | |
| 3024 | + submit_btn.prop('disabled', true); | |
| 3025 | + // make the request | |
| 3026 | + VBOCore.doAjax( | |
| 3027 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.update_taking'); ?>", | |
| 3028 | + { | |
| 3029 | + bid: '<?php echo $row['id']; ?>', | |
| 3030 | + hid: history_id, | |
| 3031 | + amount: jQuery('#new_taking_amount').val(), | |
| 3032 | + descr: jQuery('#new_taking_descr').val(), | |
| 3033 | + htype: 'PU', | |
| 3034 | + }, | |
| 3035 | + (success) => { | |
| 3036 | + // dismiss the modal | |
| 3037 | + VBOCore.emitEvent('vbo-eorder-edit-taking-dismiss'); | |
| 3038 | + // reload the page by following the response URL | |
| 3039 | + document.location.href = success.url; | |
| 3040 | + }, | |
| 3041 | + (error) => { | |
| 3042 | + // re-enable submit button | |
| 3043 | + submit_btn.prop('disabled', false); | |
| 3044 | + // display error message | |
| 3045 | + alert(error.responseText); | |
| 3046 | + } | |
| 3047 | + ); | |
| 3048 | + }); | |
| 3049 | + | |
| 3050 | + // display modal | |
| 3051 | + let modal_body = VBOCore.displayModal({ | |
| 3052 | + suffix: 'vbo-edit-taking', | |
| 3053 | + extra_class: 'vbo-modal-rounded vbo-modal-dialog', | |
| 3054 | + title: Joomla.JText._('VBO_UPDATE_PAYMENT'), | |
| 3055 | + body: '', | |
| 3056 | + body_prepend: true, | |
| 3057 | + footer_left: footer_left, | |
| 3058 | + footer_right: footer_right, | |
| 3059 | + draggable: true, | |
| 3060 | + dismiss_event: 'vbo-eorder-edit-taking-dismiss', | |
| 3061 | + onDismiss: () => { | |
| 3062 | + jQuery('.vbo-eorder-newtaking-helper-cont').appendTo( | |
| 3063 | + jQuery('.vbo-eorder-newtaking-helper-wrap') | |
| 3064 | + ); | |
| 3065 | + }, | |
| 3066 | + }); | |
| 3067 | + | |
| 3068 | + // populate helper input values | |
| 3069 | + jQuery('#new_taking_amount').val(curr_amount_paid); | |
| 3070 | + jQuery('#new_taking_payid').val('').trigger('change').prop('disabled', true); | |
| 3071 | + jQuery('#new_taking_descr').val(curr_pay_descr); | |
| 3072 | + | |
| 3073 | + // append modal body | |
| 3074 | + jQuery('.vbo-eorder-newtaking-helper-cont').appendTo(modal_body); | |
| 3075 | + }); | |
| 3076 | + | |
| 3077 | + jQuery('.vbo-booking-taking-delete').on('click', function() { | |
| 3078 | + if (!confirm(Joomla.JText._('VBDELCONFIRM'))) { | |
| 3079 | + return false; | |
| 3080 | + } | |
| 3081 | + let del_btn = jQuery(this); | |
| 3082 | + del_btn.prop('disabled', true); | |
| 3083 | + let history_id = del_btn.attr('data-historyid'); | |
| 3084 | + // make the request | |
| 3085 | + VBOCore.doAjax( | |
| 3086 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=bookings.delete_history_record'); ?>", | |
| 3087 | + { | |
| 3088 | + bid: '<?php echo $row['id']; ?>', | |
| 3089 | + hid: history_id, | |
| 3090 | + htype: 'PU', | |
| 3091 | + }, | |
| 3092 | + (success) => { | |
| 3093 | + // reload the page by following the response URL | |
| 3094 | + document.location.href = success.url; | |
| 3095 | + }, | |
| 3096 | + (error) => { | |
| 3097 | + // re-enable delete button | |
| 3098 | + del_btn.prop('disabled', false); | |
| 3099 | + // display error message | |
| 3100 | + alert(error.responseText); | |
| 3101 | + } | |
| 3102 | + ); | |
| 3103 | + }); | |
| 3104 | + | |
| 3105 | + }); | |
| 3106 | + </script> | |
| 2447 | 3107 | <?php |
| 2448 | 3108 | } |
| 2449 | 3109 | if ($history) { |
| 2450 | 3110 | ?> |
| @@ -2462,9 +3122,9 @@ | ||
| 2462 | 3122 | </thead> |
| 2463 | 3123 | <tbody> |
| 2464 | 3124 | <?php |
| 2465 | 3125 | foreach ($history as $hist) { |
| 2466 | - $hdescr = strpos($hist['descr'], '<') !== false ? $hist['descr'] : nl2br($hist['descr']); | |
| 3126 | + $hdescr = strpos((string) $hist['descr'], '<') !== false ? $hist['descr'] : nl2br((string) $hist['descr']); | |
| 2467 | 3127 | ?> |
| 2468 | 3128 | <tr class="vbo-booking-history-row"> |
| 2469 | 3129 | <td><?php echo $history_obj->validType($hist['type'], true); ?></td> |
| 2470 | 3130 | <td><?php echo JHtml::fetch('date', $hist['dt'], 'Y-m-d H:i:s'); ?></td> |
| @@ -2517,21 +3177,419 @@ | ||
| 2517 | 3177 | * |
| 2518 | 3178 | * @since 1.13 |
| 2519 | 3179 | */ |
| 2520 | 3180 | $cardlimit = mktime(23, 59, 59, $checkout_info['mon'], ($checkout_info['mday'] + 10), $checkout_info['year']); |
| 2521 | - if (time() < $cardlimit) { | |
| 2522 | - $plain_log = htmlspecialchars($row['paymentlog']); | |
| 2523 | - if (stripos($plain_log, 'card number') !== false && strpos($plain_log, '****') !== false) { | |
| 2524 | - // log contains credit card details | |
| 2525 | - // Prepare modal (Credit Card Details) | |
| 2526 | - array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-pcid', JText::translate('GETFULLCARDDETAILS'), '', 'width: 80%; height: 60%; margin-left: -40%; top: 20% !important;')); | |
| 2527 | - // end Prepare modal | |
| 3181 | + if ($current_ts < $cardlimit && $may_have_cc_details) { | |
| 3182 | + // log contains credit card details | |
| 3183 | + // prepare modal (Credit Card Details) | |
| 3184 | + array_push($vbo_modals_html, $vbo_app->getJmodalHtml('vbo-vcm-pcid', JText::translate('GETFULLCARDDETAILS'), '', 'width: 80%; height: 60%; margin-left: -40%; top: 20% !important;')); | |
| 2528 | 3185 | ?> |
| 2529 | 3186 | <div class="vcm-notif-pcidrq-container"> |
| 2530 | 3187 | <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> |
| 2531 | 3188 | </div> |
| 2532 | 3189 | <?php |
| 3190 | + /** | |
| 3191 | + * Check for automatic payment schedules support when an active CC/VCC is available. | |
| 3192 | + * | |
| 3193 | + * @since 1.16.10 (J) - 1.6.10 (WP) | |
| 3194 | + */ | |
| 3195 | + $can_payschedule = false; | |
| 3196 | + $active_payschedules = []; | |
| 3197 | + try { | |
| 3198 | + $processor = VBOModelReservation::getInstance($row, true)->getPaymentProcessor(); | |
| 3199 | + if (method_exists($processor, 'isDirectChargeSupported') && $processor->isDirectChargeSupported()) { | |
| 3200 | + // turn flag on | |
| 3201 | + $can_payschedule = true; | |
| 3202 | + // load current schedules | |
| 3203 | + $active_payschedules = VBOModelPayschedules::getInstance()->getItems([ | |
| 3204 | + 'idorder' => [ | |
| 3205 | + 'value' => $row['id'], | |
| 3206 | + ], | |
| 3207 | + ]); | |
| 3208 | + } | |
| 3209 | + } catch (Exception $e) { | |
| 3210 | + // do nothing | |
| 2533 | 3211 | } |
| 3212 | + | |
| 3213 | + if ($can_payschedule) { | |
| 3214 | + // calculate the total amount scheduled | |
| 3215 | + $tot_scheduled = 0; | |
| 3216 | + foreach ($active_payschedules as $active_payschedule) { | |
| 3217 | + if (!$active_payschedule->status) { | |
| 3218 | + $tot_scheduled += $active_payschedule->amount; | |
| 3219 | + } | |
| 3220 | + } | |
| 3221 | + | |
| 3222 | + // display action buttons for payment schedules | |
| 3223 | + ?> | |
| 3224 | + <div class="vbo-eorder-payschedules-wrap"> | |
| 3225 | + <button type="button" class="btn btn-<?php echo $active_payschedules || $automatic_payment_collection ? 'success' : 'primary'; ?> vbo-context-menu-btn vbo-context-menu-payschedules"> | |
| 3226 | + <span class="vbo-context-menu-lbl"><?php echo JText::translate('VBO_AUTOPAY_SCHEDULED'); ?></span> | |
| 3227 | + <span class="vbo-context-menu-ico"><?php VikBookingIcons::e('sort-down'); ?></span> | |
| 3228 | + </button> | |
| 3229 | + </div> | |
| 3230 | + | |
| 3231 | + <div class="vbo-eorder-newpayschedule-helper-wrap" style="display: none;"> | |
| 3232 | + <div class="vbo-eorder-newpayschedule-helper-cont" data-auto-pay-schedules="<?php echo (int) $automatic_payment_collection; ?>"> | |
| 3233 | + <p class="info" data-auto-pay-schedules="help" style="display: none;"><?php echo JText::translate('VBO_AUTO_PAY_COLLECT_HELP'); ?></p> | |
| 3234 | + <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact"> | |
| 3235 | + <div class="vbo-params-wrap"> | |
| 3236 | + <div class="vbo-params-container"> | |
| 3237 | + <div class="vbo-params-block"> | |
| 3238 | + <div class="vbo-param-container"> | |
| 3239 | + <div class="vbo-param-label"> | |
| 3240 | + <label for="new_payschedule_amount"><?php echo JText::translate('VBO_CC_AMOUNT'); ?></label> | |
| 3241 | + </div> | |
| 3242 | + <div class="vbo-param-setting"> | |
| 3243 | + <div class="vbo-input-currency-wrap"> | |
| 3244 | + <span><?php echo $currencysymb; ?></span> | |
| 3245 | + <input type="number" id="new_payschedule_amount" value="<?php echo $tot_scheduled < $row['total'] ? ($row['total'] - $tot_scheduled) : 0; ?>" min="0" step="any" /> | |
| 3246 | + </div> | |
| 3247 | + <span class="vbo-param-setting-comment"><?php echo JText::translate('VBEDITORDERNINE') . ' ' . VikBooking::formatCurrencyNumber(VikBooking::numberFormat($row['total']), $currencysymb); ?></span> | |
| 3248 | + </div> | |
| 3249 | + </div> | |
| 3250 | + <div class="vbo-param-container"> | |
| 3251 | + <div class="vbo-param-label"> | |
| 3252 | + <label for="new_payschedule_fordt"><?php echo JText::translate('VBPVIEWORDERSONE'); ?></label> | |
| 3253 | + </div> | |
| 3254 | + <div class="vbo-param-setting"> | |
| 3255 | + <?php echo $vbo_app->getCalendar(date($df, $row['checkin']), 'new_payschedule_fordt', 'new_payschedule_fordt', $nowdf, array('class'=>'', 'size'=>'10', 'maxlength'=>'19', 'todayBtn' => 'true')); ?> | |
| 3256 | + </div> | |
| 3257 | + </div> | |
| 3258 | + <div class="vbo-param-container"> | |
| 3259 | + <div class="vbo-param-label"> | |
| 3260 | + <label for="new_payschedule_fordtime"><?php echo JText::translate('VBO_REMINDER_TIME'); ?></label> | |
| 3261 | + </div> | |
| 3262 | + <div class="vbo-param-setting"> | |
| 3263 | + <select id="new_payschedule_fordtime"> | |
| 3264 | + <?php | |
| 3265 | + for ($h = 0; $h < 24; $h++) { | |
| 3266 | + $say_htime = ($h < 10 ? '0' : '') . $h; | |
| 3267 | + ?> | |
| 3268 | + <option value="<?php echo $say_htime; ?>:00"><?php echo $say_htime; ?>:00</option> | |
| 3269 | + <option value="<?php echo $say_htime; ?>:30"><?php echo $say_htime; ?>:30</option> | |
| 3270 | + <?php | |
| 3271 | + } | |
| 3272 | + ?> | |
| 3273 | + </select> | |
| 3274 | + </div> | |
| 3275 | + </div> | |
| 3276 | + </div> | |
| 3277 | + </div> | |
| 3278 | + </div> | |
| 3279 | + </div> | |
| 3280 | + </div> | |
| 3281 | + </div> | |
| 3282 | + | |
| 3283 | + <script type="text/javascript"> | |
| 3284 | + | |
| 3285 | + // build base buttons list for context menu | |
| 3286 | + var vbo_payschedule_btns = [ | |
| 3287 | + // toggle automatic payment collection scheduling for all bookings | |
| 3288 | + { | |
| 3289 | + activeState: <?php echo $automatic_payment_collection ? 'true' : 'false'; ?>, | |
| 3290 | + text: <?php echo json_encode(JText::translate('VBO_ENABLED_FOR_ALL_BOOKINGS')); ?>, | |
| 3291 | + separator: true, | |
| 3292 | + icon: function() { | |
| 3293 | + return this.activeState ? '<?php echo VikBookingIcons::i('toggle-on', 'vbo-enabled-icon'); ?>' : '<?php echo VikBookingIcons::i('toggle-off'); ?>'; | |
| 3294 | + }, | |
| 3295 | + action: function(root, event) { | |
| 3296 | + // create reference to button object | |
| 3297 | + let that = this; | |
| 3298 | + | |
| 3299 | + // get new state | |
| 3300 | + let newState = !this.activeState; | |
| 3301 | + | |
| 3302 | + // determine confirmation message | |
| 3303 | + let confirm_enable = <?php echo json_encode(JText::translate('VBO_AUTO_PAY_COLLECT_ENABLE_CONF')); ?>; | |
| 3304 | + let confirm_disable = <?php echo json_encode(JText::translate('VBO_AUTO_PAY_COLLECT_DISABLE_CONF')); ?>; | |
| 3305 | + | |
| 3306 | + if ((newState && confirm(confirm_enable)) || (!newState && confirm(confirm_disable))) { | |
| 3307 | + // silently update configuration setting | |
| 3308 | + VBOCore.doAjax( | |
| 3309 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=configuration.update'); ?>", | |
| 3310 | + { | |
| 3311 | + settings: { | |
| 3312 | + auto_payment_collection: newState ? 1 : 0, | |
| 3313 | + } | |
| 3314 | + }, | |
| 3315 | + (success) => { | |
| 3316 | + // toggle state | |
| 3317 | + that.activeState = newState; | |
| 3318 | + // update data attribute with the newly saved configuration value | |
| 3319 | + let statusEl = document.querySelector('.vbo-eorder-newpayschedule-helper-cont[data-auto-pay-schedules]'); | |
| 3320 | + if (statusEl) { | |
| 3321 | + statusEl.setAttribute('data-auto-pay-schedules', (newState ? 1 : 0)); | |
| 3322 | + } | |
| 3323 | + }, | |
| 3324 | + (error) => { | |
| 3325 | + console.error(error); | |
| 3326 | + } | |
| 3327 | + ); | |
| 3328 | + } | |
| 3329 | + }, | |
| 3330 | + }, | |
| 3331 | + // add new payment schedule button | |
| 3332 | + { | |
| 3333 | + icon: '<?php echo VikBookingIcons::i('plus-circle'); ?>', | |
| 3334 | + text: Joomla.JText._('VBO_NEW_PAYSCHEDULE'), | |
| 3335 | + separator: true, | |
| 3336 | + action: (root, config) => { | |
| 3337 | + // build modal buttons | |
| 3338 | + let footer_left = jQuery('<button></button>'); | |
| 3339 | + footer_left.addClass('btn'); | |
| 3340 | + footer_left.attr('type', 'button'); | |
| 3341 | + footer_left.text(Joomla.JText._('VBANNULLA')); | |
| 3342 | + footer_left.on('click', function() { | |
| 3343 | + // dismiss the modal | |
| 3344 | + VBOCore.emitEvent('vbo-eorder-new-payschedule-dismiss'); | |
| 3345 | + }); | |
| 3346 | + | |
| 3347 | + let footer_right = jQuery('<button></button>'); | |
| 3348 | + footer_right.addClass('btn btn-success'); | |
| 3349 | + footer_right.attr('type', 'button'); | |
| 3350 | + footer_right.text(Joomla.JText._('VBSAVE')); | |
| 3351 | + footer_right.on('click', function() { | |
| 3352 | + // disable button to prevent double submissions | |
| 3353 | + let submit_btn = jQuery(this); | |
| 3354 | + submit_btn.prop('disabled', true); | |
| 3355 | + // make the request | |
| 3356 | + VBOCore.doAjax( | |
| 3357 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=payschedules.save'); ?>", | |
| 3358 | + { | |
| 3359 | + bid: '<?php echo $row['id']; ?>', | |
| 3360 | + amount: jQuery('#new_payschedule_amount').val(), | |
| 3361 | + dt: jQuery('#new_payschedule_fordt').val(), | |
| 3362 | + time: jQuery('#new_payschedule_fordtime').val(), | |
| 3363 | + }, | |
| 3364 | + (new_pay_schedules) => { | |
| 3365 | + // re-enable submit button | |
| 3366 | + submit_btn.prop('disabled', false); | |
| 3367 | + // dismiss the modal | |
| 3368 | + VBOCore.emitEvent('vbo-eorder-new-payschedule-dismiss'); | |
| 3369 | + // populate the new schedule buttons | |
| 3370 | + let new_pay_schedule_btns = []; | |
| 3371 | + // push button to toggle automatic payment collection scheduling for all bookings | |
| 3372 | + new_pay_schedule_btns.push(vbo_payschedule_btns[0]); | |
| 3373 | + // push button to add a new schedule | |
| 3374 | + new_pay_schedule_btns.push(vbo_payschedule_btns[1]); | |
| 3375 | + // push all active schedules | |
| 3376 | + new_pay_schedules.forEach((payschedule) => { | |
| 3377 | + new_pay_schedule_btns.push( | |
| 3378 | + vboBuildPayScheduleBtn(payschedule) | |
| 3379 | + ); | |
| 3380 | + }); | |
| 3381 | + // update trigger button class | |
| 3382 | + if (new_pay_schedules.length) { | |
| 3383 | + jQuery('.vbo-context-menu-payschedules').removeClass('btn-primary').addClass('btn-success'); | |
| 3384 | + } else { | |
| 3385 | + jQuery('.vbo-context-menu-payschedules').removeClass('btn-success').addClass('btn-primary'); | |
| 3386 | + } | |
| 3387 | + // set new buttons in context menu | |
| 3388 | + jQuery('.vbo-context-menu-payschedules').vboContextMenu('buttons', new_pay_schedule_btns); | |
| 3389 | + }, | |
| 3390 | + (error) => { | |
| 3391 | + // re-enable submit button | |
| 3392 | + submit_btn.prop('disabled', false); | |
| 3393 | + // display error message | |
| 3394 | + alert(error.responseText); | |
| 3395 | + } | |
| 3396 | + ); | |
| 3397 | + }); | |
| 3398 | + | |
| 3399 | + // display modal | |
| 3400 | + let modal_body = VBOCore.displayModal({ | |
| 3401 | + suffix: 'vbo-new-pay-schedule', | |
| 3402 | + extra_class: 'vbo-modal-rounded vbo-modal-dialog', | |
| 3403 | + title: Joomla.JText._('VBO_NEW_PAYSCHEDULE'), | |
| 3404 | + body: '', | |
| 3405 | + body_prepend: true, | |
| 3406 | + footer_left: footer_left, | |
| 3407 | + footer_right: footer_right, | |
| 3408 | + draggable: true, | |
| 3409 | + dismiss_event: 'vbo-eorder-new-payschedule-dismiss', | |
| 3410 | + onDismiss: () => { | |
| 3411 | + jQuery('.vbo-eorder-newpayschedule-helper-cont').appendTo( | |
| 3412 | + jQuery('.vbo-eorder-newpayschedule-helper-wrap') | |
| 3413 | + ); | |
| 3414 | + }, | |
| 3415 | + }); | |
| 3416 | + | |
| 3417 | + // check current automatic payment schedules status | |
| 3418 | + let statusEl = document.querySelector('.vbo-eorder-newpayschedule-helper-cont[data-auto-pay-schedules]'); | |
| 3419 | + if (statusEl) { | |
| 3420 | + let autoPayStatus = statusEl.getAttribute('data-auto-pay-schedules'); | |
| 3421 | + if (autoPayStatus == 1) { | |
| 3422 | + // show help element | |
| 3423 | + statusEl.querySelector('[data-auto-pay-schedules="help"]').style.display = ''; | |
| 3424 | + } else { | |
| 3425 | + // hide help element | |
| 3426 | + statusEl.querySelector('[data-auto-pay-schedules="help"]').style.display = 'none'; | |
| 3427 | + } | |
| 3428 | + } | |
| 3429 | + | |
| 3430 | + // append modal body | |
| 3431 | + jQuery('.vbo-eorder-newpayschedule-helper-cont').appendTo(modal_body); | |
| 3432 | + }, | |
| 3433 | + } | |
| 3434 | + ]; | |
| 3435 | + | |
| 3436 | + /** | |
| 3437 | + * Builds a button object for the context menu from the given payment schedule object. | |
| 3438 | + */ | |
| 3439 | + function vboBuildPayScheduleBtn(payschedule) { | |
| 3440 | + let icn_to_process = '<?php echo VikBookingIcons::i('clock'); ?>'; | |
| 3441 | + let icn_processed = '<?php echo VikBookingIcons::i('check-circle'); ?>'; | |
| 3442 | + let icn_error = '<?php echo VikBookingIcons::i('exclamation-triangle'); ?>'; | |
| 3443 | + let dt_unit = (payschedule.dt_diff.days || payschedule.dt_diff.weeks || payschedule.dt_diff.months || payschedule.dt_diff.years || 0); | |
| 3444 | + let say_dt = !payschedule.dt_diff.past && dt_unit > 0 ? payschedule.dt_diff.relative : payschedule?.fordt; | |
| 3445 | + if (!payschedule.dt_diff.past && (payschedule.dt_diff.sameday || payschedule.dt_diff.today)) { | |
| 3446 | + say_dt = payschedule.dt_diff.relative + ' (' + payschedule.time_hm + ')'; | |
| 3447 | + } else if (!payschedule.dt_diff.past && payschedule.dt_diff.tomorrow) { | |
| 3448 | + say_dt = payschedule.dt_diff.relative + ' (' + payschedule.time_hm + ')'; | |
| 3449 | + } | |
| 3450 | + | |
| 3451 | + return { | |
| 3452 | + icon: ((payschedule.status || 0) > 0 ? (payschedule.status == 1 ? icn_processed : icn_error) : icn_to_process), | |
| 3453 | + text: VBOCore.getCurrency().format(payschedule?.amount) + ' - ' + say_dt, | |
| 3454 | + class: ((payschedule.status || 0) == 1 ? 'vbo-context-menu-entry-success' : ((payschedule.status || 0) == 2 ? 'vbo-context-menu-entry-warning' : 'vbo-context-menu-entry-danger')), | |
| 3455 | + separator: false, | |
| 3456 | + action: (root, config) => { | |
| 3457 | + if (payschedule.status == 0 || !payschedule.logs) { | |
| 3458 | + // confirm deletion without displaying anything | |
| 3459 | + if (confirm(Joomla.JText._('VBDELCONFIRM'))) { | |
| 3460 | + // make the request | |
| 3461 | + VBOCore.doAjax( | |
| 3462 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=payschedules.delete'); ?>", | |
| 3463 | + { | |
| 3464 | + bid: payschedule.idorder, | |
| 3465 | + schedule_id: payschedule.id, | |
| 3466 | + }, | |
| 3467 | + (new_pay_schedules) => { | |
| 3468 | + // populate the new schedule buttons | |
| 3469 | + let new_pay_schedule_btns = []; | |
| 3470 | + // push button to toggle automatic payment collection scheduling for all bookings | |
| 3471 | + new_pay_schedule_btns.push(vbo_payschedule_btns[0]); | |
| 3472 | + // push button to add a new schedule | |
| 3473 | + new_pay_schedule_btns.push(vbo_payschedule_btns[1]); | |
| 3474 | + // push all active schedules | |
| 3475 | + new_pay_schedules.forEach((payschedule) => { | |
| 3476 | + new_pay_schedule_btns.push( | |
| 3477 | + vboBuildPayScheduleBtn(payschedule) | |
| 3478 | + ); | |
| 3479 | + }); | |
| 3480 | + // update trigger button class | |
| 3481 | + if (new_pay_schedules.length) { | |
| 3482 | + jQuery('.vbo-context-menu-payschedules').removeClass('btn-primary').addClass('btn-success'); | |
| 3483 | + } else { | |
| 3484 | + jQuery('.vbo-context-menu-payschedules').removeClass('btn-success').addClass('btn-primary'); | |
| 3485 | + } | |
| 3486 | + // set new buttons in context menu | |
| 3487 | + jQuery('.vbo-context-menu-payschedules').vboContextMenu('buttons', new_pay_schedule_btns); | |
| 3488 | + }, | |
| 3489 | + (error) => { | |
| 3490 | + // display error message | |
| 3491 | + alert(error.responseText); | |
| 3492 | + } | |
| 3493 | + ); | |
| 3494 | + } | |
| 3495 | + } else { | |
| 3496 | + // display modal on click with the execution logs | |
| 3497 | + | |
| 3498 | + // build modal buttons | |
| 3499 | + let footer_left = jQuery('<button></button>'); | |
| 3500 | + footer_left.addClass('btn'); | |
| 3501 | + footer_left.attr('type', 'button'); | |
| 3502 | + footer_left.text(Joomla.JText._('VBANNULLA')); | |
| 3503 | + footer_left.on('click', function() { | |
| 3504 | + // dismiss the modal | |
| 3505 | + VBOCore.emitEvent('vbo-eorder-payschedule-logs-dismiss'); | |
| 3506 | + }); | |
| 3507 | + | |
| 3508 | + let footer_right = jQuery('<button></button>'); | |
| 3509 | + footer_right.addClass('btn btn-danger'); | |
| 3510 | + footer_right.attr('type', 'button'); | |
| 3511 | + footer_right.text(Joomla.JText._('VBELIMINA')); | |
| 3512 | + footer_right.on('click', function() { | |
| 3513 | + // confirm record deletion | |
| 3514 | + if (confirm(Joomla.JText._('VBDELCONFIRM'))) { | |
| 3515 | + // make the request | |
| 3516 | + VBOCore.doAjax( | |
| 3517 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=payschedules.delete'); ?>", | |
| 3518 | + { | |
| 3519 | + bid: payschedule.idorder, | |
| 3520 | + schedule_id: payschedule.id, | |
| 3521 | + }, | |
| 3522 | + (new_pay_schedules) => { | |
| 3523 | + // dismiss the modal | |
| 3524 | + VBOCore.emitEvent('vbo-eorder-payschedule-logs-dismiss'); | |
| 3525 | + // populate the new schedule buttons | |
| 3526 | + let new_pay_schedule_btns = []; | |
| 3527 | + // push button to toggle automatic payment collection scheduling for all bookings | |
| 3528 | + new_pay_schedule_btns.push(vbo_payschedule_btns[0]); | |
| 3529 | + // push button to add a new schedule | |
| 3530 | + new_pay_schedule_btns.push(vbo_payschedule_btns[1]); | |
| 3531 | + // push all active schedules | |
| 3532 | + new_pay_schedules.forEach((payschedule) => { | |
| 3533 | + new_pay_schedule_btns.push( | |
| 3534 | + vboBuildPayScheduleBtn(payschedule) | |
| 3535 | + ); | |
| 3536 | + }); | |
| 3537 | + // update trigger button class | |
| 3538 | + if (new_pay_schedules.length) { | |
| 3539 | + jQuery('.vbo-context-menu-payschedules').removeClass('btn-primary').addClass('btn-success'); | |
| 3540 | + } else { | |
| 3541 | + jQuery('.vbo-context-menu-payschedules').removeClass('btn-success').addClass('btn-primary'); | |
| 3542 | + } | |
| 3543 | + // set new buttons in context menu | |
| 3544 | + jQuery('.vbo-context-menu-payschedules').vboContextMenu('buttons', new_pay_schedule_btns); | |
| 3545 | + }, | |
| 3546 | + (error) => { | |
| 3547 | + // display error message | |
| 3548 | + alert(error.responseText); | |
| 3549 | + } | |
| 3550 | + ); | |
| 3551 | + } | |
| 3552 | + }); | |
| 3553 | + | |
| 3554 | + // display modal | |
| 3555 | + let modal_body = VBOCore.displayModal({ | |
| 3556 | + suffix: 'vbo-pay-schedule-logs', | |
| 3557 | + extra_class: 'vbo-modal-rounded vbo-modal-dialog', | |
| 3558 | + title: payschedule.fordt, | |
| 3559 | + body: '<pre>' + payschedule.logs + '</pre>', | |
| 3560 | + footer_left: footer_left, | |
| 3561 | + footer_right: footer_right, | |
| 3562 | + draggable: true, | |
| 3563 | + dismiss_event: 'vbo-eorder-payschedule-logs-dismiss', | |
| 3564 | + }); | |
| 3565 | + } | |
| 3566 | + }, | |
| 3567 | + }; | |
| 3568 | + } | |
| 3569 | + | |
| 3570 | + // build context menu | |
| 3571 | + jQuery(function() { | |
| 3572 | + | |
| 3573 | + // append active payment schedule buttons | |
| 3574 | + let active_payschedules = <?php echo json_encode($active_payschedules); ?>; | |
| 3575 | + active_payschedules.forEach((payschedule) => { | |
| 3576 | + vbo_payschedule_btns.push( | |
| 3577 | + vboBuildPayScheduleBtn(payschedule) | |
| 3578 | + ); | |
| 3579 | + }); | |
| 3580 | + | |
| 3581 | + // render context menu | |
| 3582 | + jQuery('.vbo-context-menu-payschedules').vboContextMenu({ | |
| 3583 | + placement: 'bottom-left', | |
| 3584 | + buttons: vbo_payschedule_btns, | |
| 3585 | + }); | |
| 3586 | + | |
| 3587 | + }); | |
| 3588 | + </script> | |
| 3589 | + <?php | |
| 3590 | + } | |
| 3591 | + // end automatic payment schedules | |
| 2534 | 3592 | } |
| 2535 | 3593 | } |
| 2536 | 3594 | } elseif (empty($row['idorderota']) && !empty($row['paymentlog']) && $row['status'] == 'standby') { |
| 2537 | 3595 | ?> |
| @@ -2560,9 +3618,9 @@ | ||
| 2560 | 3618 | <?php |
| 2561 | 3619 | // render the reporting-invalidcc layout |
| 2562 | 3620 | echo JLayoutHelper::render('reporting.invalidcc', $layout_data, null, [ |
| 2563 | 3621 | 'component' => 'com_vikchannelmanager', |
| 2564 | - 'client' => 'administrator', | |
| 3622 | + 'client' => 'admin', | |
| 2565 | 3623 | ]); |
| 2566 | 3624 | ?> |
| 2567 | 3625 | </div> |
| 2568 | 3626 | <?php |
| @@ -2653,90 +3711,94 @@ | ||
| 2653 | 3711 | <input type="hidden" name="cid[]" value="<?php echo $row['id']; ?>" /> |
| 2654 | 3712 | <input type="hidden" name="invnotes" id="invnotes-hid" value="" /> |
| 2655 | 3713 | </form> |
| 2656 | 3714 | |
| 2657 | -<div class="vbo-modal-overlay-block vbo-modal-overlay-block-sms-email"> | |
| 2658 | - <a class="vbo-modal-overlay-close" href="javascript: void(0);"></a> | |
| 2659 | - <div class="vbo-modal-overlay-content vbo-modal-overlay-content-large vbo-modal-overlay-content-sms-email"> | |
| 3715 | +<div class="vbo-editorder-sms-email-send-helper" style="display: none;"> | |
| 2660 | 3716 | |
| 2661 | - <div class="vbo-modal-overlay-content-head vbo-modal-overlay-content-sms-email-head"> | |
| 2662 | - <h3> | |
| 2663 | - <span></span> | |
| 2664 | - <span class="vbo-modal-overlay-close-times" onclick="vboToggleSendEmail();">×</span> | |
| 2665 | - </h3> | |
| 2666 | - </div> | |
| 3717 | + <div class="vbo-editorder-sms-send-wrap"> | |
| 3718 | + <form action="index.php?option=com_vikbooking" method="post" id="vbo-modal-form-sms"> | |
| 3719 | + <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact"> | |
| 3720 | + <div class="vbo-params-wrap"> | |
| 3721 | + <div class="vbo-params-container"> | |
| 2667 | 3722 | |
| 2668 | - <div class="vbo-modal-overlay-content-body vbo-modal-overlay-content-body-scroll"> | |
| 3723 | + <div class="vbo-param-container vbo-param-container-full"> | |
| 3724 | + <div class="vbo-param-label"> | |
| 3725 | + <label for="smscont"><?php echo JText::translate('VBSENDSMSCUSTCONT'); ?></label> | |
| 3726 | + </div> | |
| 3727 | + <div class="vbo-param-setting"> | |
| 3728 | + <textarea name="smscont" id="smscont" style="width: 99%; min-width: 99%; max-width: 99%; height: 120px;"></textarea> | |
| 3729 | + </div> | |
| 3730 | + </div> | |
| 2669 | 3731 | |
| 2670 | - <div id="vbo-overlay-sms-cont" style="display: none;"> | |
| 2671 | - <h4 style="display: none;"><?php echo JText::translate('VBSENDSMSACTION'); ?>: <span id="smstophone-lbl"><?php echo $row['phone']; ?></span></h4> | |
| 2672 | - <form action="index.php?option=com_vikbooking" method="post" id="vbo-modal-form-sms"> | |
| 2673 | - <div class="vbo-calendar-cfield-entry"> | |
| 2674 | - <label for="smscont"><?php echo JText::translate('VBSENDSMSCUSTCONT'); ?></label> | |
| 2675 | - <span><textarea name="smscont" id="smscont" style="width: 99%; min-width: 99%;max-width: 99%; height: 120px;"></textarea></span> | |
| 2676 | 3732 | </div> |
| 2677 | - <input type="hidden" name="phone" id="smstophone" value="<?php echo $row['phone']; ?>" /> | |
| 2678 | - <input type="hidden" name="goto" value="<?php echo urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id']); ?>" /> | |
| 2679 | - <input type="hidden" name="task" value="sendcustomsms" /> | |
| 2680 | - </form> | |
| 3733 | + </div> | |
| 2681 | 3734 | </div> |
| 3735 | + <input type="hidden" name="phone" id="smstophone" value="<?php echo $row['phone']; ?>" /> | |
| 3736 | + <input type="hidden" name="goto" value="<?php echo urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id']); ?>" /> | |
| 3737 | + <input type="hidden" name="task" value="sendcustomsms" /> | |
| 3738 | + </form> | |
| 3739 | + </div> | |
| 2682 | 3740 | |
| 2683 | - <div id="vbo-overlay-email-cont" style="display: none;"> | |
| 2684 | - <h4 style="display: none;"><?php echo JText::translate('VBSENDEMAILACTION'); ?>: <span id="emailto-lbl"><?php echo $row['custmail']; ?></span></h4> | |
| 2685 | - <form action="index.php?option=com_vikbooking" method="post" enctype="multipart/form-data" id="vbo-modal-form-email"> | |
| 2686 | - <input type="hidden" name="bid" value="<?php echo $row['id']; ?>" /> | |
| 2687 | - <?php | |
| 2688 | - $q = "SELECT `setting` FROM `#__vikbooking_config` WHERE `param`='customemailtpls';"; | |
| 2689 | - $dbo->setQuery($q); | |
| 2690 | - $cur_emtpl = $dbo->loadResult(); | |
| 3741 | + <div class="vbo-editorder-email-send-wrap"> | |
| 3742 | + <form action="index.php?option=com_vikbooking" method="post" enctype="multipart/form-data" id="vbo-modal-form-email"> | |
| 3743 | + <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact"> | |
| 3744 | + <div class="vbo-params-wrap"> | |
| 3745 | + <div class="vbo-params-container"> | |
| 2691 | 3746 | |
| 2692 | - $cur_emtpl = empty($cur_emtpl) ? array() : json_decode($cur_emtpl, true); | |
| 2693 | - $cur_emtpl = is_array($cur_emtpl) ? $cur_emtpl : array(); | |
| 3747 | + <?php | |
| 3748 | + $cur_emtpl = VBOFactory::getConfig()->getArray('customemailtpls', []); | |
| 3749 | + if ($cur_emtpl) { | |
| 3750 | + ?> | |
| 3751 | + <div class="vbo-param-container"> | |
| 3752 | + <div class="vbo-param-setting"> | |
| 3753 | + <select id="emtpl-customemail" onchange="vboLoadEmailTpl(this.value);"> | |
| 3754 | + <option value=""><?php echo JText::translate('VBEMAILCUSTFROMTPL'); ?></option> | |
| 3755 | + <?php | |
| 3756 | + foreach ($cur_emtpl as $emk => $emv) { | |
| 3757 | + ?> | |
| 3758 | + <optgroup label="<?php echo $emv['emailsubj']; ?>"> | |
| 3759 | + <option value="<?php echo $emk; ?>"><?php echo JText::translate('VBEMAILCUSTFROMTPLUSE'); ?></option> | |
| 3760 | + <option value="rm<?php echo $emk; ?>"><?php echo JText::translate('VBEMAILCUSTFROMTPLRM'); ?></option> | |
| 3761 | + </optgroup> | |
| 3762 | + <?php | |
| 3763 | + } | |
| 3764 | + ?> | |
| 3765 | + </select> | |
| 3766 | + </div> | |
| 3767 | + </div> | |
| 3768 | + <?php | |
| 3769 | + } | |
| 2694 | 3770 | |
| 2695 | - if ($cur_emtpl) { | |
| 2696 | - ?> | |
| 2697 | - <div class="vbo-calendar-custmail-tpls-wrap"> | |
| 2698 | - <select id="emtpl-customemail" onchange="vboLoadEmailTpl(this.value);"> | |
| 2699 | - <option value=""><?php echo JText::translate('VBEMAILCUSTFROMTPL'); ?></option> | |
| 2700 | - <?php | |
| 2701 | - foreach ($cur_emtpl as $emk => $emv) { | |
| 2702 | - ?> | |
| 2703 | - <optgroup label="<?php echo $emv['emailsubj']; ?>"> | |
| 2704 | - <option value="<?php echo $emk; ?>"><?php echo JText::translate('VBEMAILCUSTFROMTPLUSE'); ?></option> | |
| 2705 | - <option value="rm<?php echo $emk; ?>"><?php echo JText::translate('VBEMAILCUSTFROMTPLRM'); ?></option> | |
| 2706 | - </optgroup> | |
| 2707 | - <?php | |
| 3771 | + /** | |
| 3772 | + * Load all conditional text special tags. | |
| 3773 | + * | |
| 3774 | + * @since 1.14 (J) - 1.4.0 (WP) | |
| 3775 | + */ | |
| 3776 | + $extra_btns = []; | |
| 3777 | + $condtext_tags = VikBooking::getConditionalRulesInstance()->getSpecialTags(); | |
| 3778 | + if ($condtext_tags) { | |
| 3779 | + $condtext_tags = array_keys($condtext_tags); | |
| 3780 | + foreach ($condtext_tags as $tag) { | |
| 3781 | + array_push($extra_btns, '<button type="button" class="btn btn-secondary btn-small vbo-condtext-specialtag-btn" onclick="setSpecialTplTag(\'emailcont\', \'' . $tag . '\');">' . $tag . '</button>'); | |
| 2708 | 3782 | } |
| 2709 | - ?> | |
| 2710 | - </select> | |
| 2711 | - </div> | |
| 2712 | - <?php | |
| 2713 | - } | |
| 2714 | - | |
| 2715 | - /** | |
| 2716 | - * Load all conditional text special tags. | |
| 2717 | - * | |
| 2718 | - * @since 1.14 (J) - 1.4.0 (WP) | |
| 2719 | - */ | |
| 2720 | - $extra_btns = array(); | |
| 2721 | - $condtext_tags = VikBooking::getConditionalRulesInstance()->getSpecialTags(); | |
| 2722 | - if (count($condtext_tags)) { | |
| 2723 | - $condtext_tags = array_keys($condtext_tags); | |
| 2724 | - foreach ($condtext_tags as $tag) { | |
| 2725 | - array_push($extra_btns, '<button type="button" class="btn btn-secondary btn-small vbo-condtext-specialtag-btn" onclick="setSpecialTplTag(\'emailcont\', \'' . $tag . '\');">' . $tag . '</button>'); | |
| 2726 | 3783 | } |
| 2727 | - } | |
| 2728 | - // | |
| 2729 | - ?> | |
| 2730 | - <div class="vbo-calendar-cfields-wrap"> | |
| 2731 | - <div class="vbo-calendar-cfield-entry"> | |
| 2732 | - <label for="emailsubj"><?php echo JText::translate('VBSENDEMAILCUSTSUBJ'); ?></label> | |
| 2733 | - <span><input type="text" name="emailsubj" id="emailsubj" value="" size="30" /></span> | |
| 3784 | + ?> | |
| 3785 | + <div class="vbo-param-container vbo-param-container-full"> | |
| 3786 | + <div class="vbo-param-label"> | |
| 3787 | + <label for="emailsubj"><?php echo JText::translate('VBSENDEMAILCUSTSUBJ'); ?></label> | |
| 3788 | + </div> | |
| 3789 | + <div class="vbo-param-setting"> | |
| 3790 | + <input type="text" name="emailsubj" id="emailsubj" value="" size="30" /> | |
| 3791 | + </div> | |
| 2734 | 3792 | </div> |
| 2735 | - <div class="vbo-calendar-cfield-entry"> | |
| 2736 | - <label for="emailcont"><?php echo JText::translate('VBSENDEMAILCUSTCONT'); ?></label> | |
| 3793 | + | |
| 3794 | + <div class="vbo-param-container vbo-param-container-full"> | |
| 3795 | + <div class="vbo-param-label"> | |
| 3796 | + <label for="emailcont"><?php echo JText::translate('VBSENDEMAILCUSTCONT'); ?></label> | |
| 3797 | + </div> | |
| 3798 | + <div class="vbo-param-setting"> | |
| 2737 | 3799 | <?php |
| 2738 | - $special_tags_base = array( | |
| 3800 | + $special_tags_base = [ | |
| 2739 | 3801 | '{customer_name}', |
| 2740 | 3802 | '{booking_id}', |
| 2741 | 3803 | '{checkin_date}', |
| 2742 | 3804 | '{checkout_date}', |
| @@ -2749,9 +3811,9 @@ | ||
| 2749 | 3811 | '{total}', |
| 2750 | 3812 | '{total_paid}', |
| 2751 | 3813 | '{remaining_balance}', |
| 2752 | 3814 | '{booking_link}', |
| 2753 | - ); | |
| 3815 | + ]; | |
| 2754 | 3816 | |
| 2755 | 3817 | $special_tags_base_html = ''; |
| 2756 | 3818 | foreach ($special_tags_base as $sp_tag) { |
| 2757 | 3819 | $special_tags_base_html .= '<button type="button" class="btn btn-secondary btn-small" onclick="setSpecialTplTag(\'emailcont\', \'' . $sp_tag . '\');">' . $sp_tag . '</button>' . "\n"; |
| @@ -2761,110 +3823,211 @@ | ||
| 2761 | 3823 | * Use the rich text editor (visual editor) to build custom email messages. |
| 2762 | 3824 | * |
| 2763 | 3825 | * @since 1.15.0 (J) - 1.5.0 (WP) |
| 2764 | 3826 | */ |
| 2765 | - $tarea_attr = array( | |
| 3827 | + $tarea_attr = [ | |
| 2766 | 3828 | 'id' => 'emailcont', |
| 2767 | 3829 | 'rows' => '7', |
| 2768 | 3830 | 'cols' => '170', |
| 2769 | 3831 | 'style' => 'width: 99%; min-width: 99%; max-width: 99%; height: 120px; margin-bottom: 1px;', |
| 2770 | - ); | |
| 2771 | - $editor_opts = array( | |
| 2772 | - 'modes' => array( | |
| 3832 | + ]; | |
| 3833 | + $editor_opts = [ | |
| 3834 | + 'modes' => [ | |
| 3835 | + 'visual', | |
| 2773 | 3836 | 'text', |
| 2774 | - 'visual', | |
| 2775 | - ), | |
| 2776 | - ); | |
| 3837 | + ], | |
| 3838 | + 'gen_ai' => [ | |
| 3839 | + 'booking' => $row, | |
| 3840 | + 'customer' => $customer, | |
| 3841 | + 'environment' => 'booking', | |
| 3842 | + ], | |
| 3843 | + ]; | |
| 2777 | 3844 | $editor_btns = $special_tags_base; |
| 2778 | - if (count($condtext_tags)) { | |
| 3845 | + if ($condtext_tags) { | |
| 2779 | 3846 | $editor_btns = array_merge($editor_btns, $condtext_tags); |
| 2780 | 3847 | } |
| 3848 | + | |
| 3849 | + /** | |
| 3850 | + * Trigger event to allow third-party plugins to add custom special tags. | |
| 3851 | + * | |
| 3852 | + * @since 1.16.10 (J) - 1.6.10 (WP) | |
| 3853 | + */ | |
| 3854 | + $custom_btns = VBOFactory::getPlatform()->getDispatcher()->filter('onRenderCustomEmailSpecialTags', [$row, $editor_btns]); | |
| 3855 | + foreach ($custom_btns as $custom_btn) { | |
| 3856 | + // merge custom buttons | |
| 3857 | + $editor_btns = array_merge($editor_btns, (array) $custom_btn); | |
| 3858 | + } | |
| 3859 | + | |
| 3860 | + // make sure to filter empty buttons | |
| 3861 | + $editor_btns = array_filter($editor_btns); | |
| 3862 | + | |
| 3863 | + // render visual editor | |
| 2781 | 3864 | echo $vbo_app->renderVisualEditor('emailcont', '', $tarea_attr, $editor_opts, $editor_btns); |
| 2782 | 3865 | ?> |
| 2783 | - <div class="btn-group pull-left vbo-smstpl-bgroup vbo-custmail-bgroup vik-contentbuilder-textmode-sptags"> | |
| 2784 | - <?php echo $special_tags_base_html . "\n" . implode("\n", $extra_btns); ?> | |
| 3866 | + <div class="btn-group pull-left vbo-smstpl-bgroup vbo-custmail-bgroup vik-contentbuilder-textmode-sptags"> | |
| 3867 | + <?php echo $special_tags_base_html . "\n" . implode("\n", $extra_btns); ?> | |
| 3868 | + </div> | |
| 2785 | 3869 | </div> |
| 2786 | 3870 | </div> |
| 2787 | - <div class="vbo-calendar-cfield-entry"> | |
| 2788 | - <label for="emailattch"><?php echo JText::translate('VBSENDEMAILCUSTATTCH'); ?></label> | |
| 2789 | - <span><input type="file" name="emailattch" id="emailattch" /></span> | |
| 3871 | + | |
| 3872 | + <div class="vbo-param-container vbo-param-container-full"> | |
| 3873 | + <div class="vbo-param-label"> | |
| 3874 | + <label for="emailattch"><?php echo JText::translate('VBSENDEMAILCUSTATTCH'); ?></label> | |
| 3875 | + </div> | |
| 3876 | + <div class="vbo-param-setting"> | |
| 3877 | + <input type="file" name="emailattch" id="emailattch" /> | |
| 3878 | + </div> | |
| 2790 | 3879 | </div> |
| 2791 | - <div class="vbo-calendar-cfield-entry"> | |
| 2792 | - <label for="emailfrom"><?php echo JText::translate('VBSENDEMAILCUSTFROM'); ?></label> | |
| 2793 | - <span><input type="text" name="emailfrom" id="emailfrom" value="<?php echo VikBooking::getSenderMail(); ?>" size="30" /></span> | |
| 3880 | + | |
| 3881 | + <div class="vbo-param-container vbo-param-container-full"> | |
| 3882 | + <div class="vbo-param-label"> | |
| 3883 | + <label for="emailfrom"><?php echo JText::translate('VBSENDEMAILCUSTFROM'); ?></label> | |
| 3884 | + </div> | |
| 3885 | + <div class="vbo-param-setting"> | |
| 3886 | + <input type="text" name="emailfrom" id="emailfrom" value="<?php echo VikBooking::getSenderMail(); ?>" size="30" /> | |
| 3887 | + </div> | |
| 2794 | 3888 | </div> |
| 3889 | + | |
| 2795 | 3890 | </div> |
| 2796 | - <input type="hidden" name="email" id="emailto" value="<?php echo $row['custmail']; ?>" /> | |
| 2797 | - <input type="hidden" name="goto" value="<?php echo urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id']); ?>" /> | |
| 2798 | - <input type="hidden" name="task" value="sendcustomemail" /> | |
| 2799 | - </form> | |
| 3891 | + </div> | |
| 2800 | 3892 | </div> |
| 3893 | + <input type="hidden" name="bid" value="<?php echo $row['id']; ?>" /> | |
| 3894 | + <input type="hidden" name="email" id="emailto" value="<?php echo $row['custmail']; ?>" /> | |
| 3895 | + <input type="hidden" name="goto" value="<?php echo urlencode('index.php?option=com_vikbooking&task=editorder&cid[]='.$row['id']); ?>" /> | |
| 3896 | + <input type="hidden" name="task" value="sendcustomemail" /> | |
| 3897 | + </form> | |
| 3898 | + </div> | |
| 2801 | 3899 | |
| 2802 | - </div> | |
| 3900 | + <div id="vbo-modal-footer-sms" style="display: none;"> | |
| 3901 | + <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> | |
| 3902 | + </div> | |
| 3903 | + <div id="vbo-modal-footer-email" style="display: none;"> | |
| 3904 | + <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> | |
| 3905 | + </div> | |
| 3906 | +</div> | |
| 2803 | 3907 | |
| 2804 | - <div class="vbo-modal-overlay-content-footer"> | |
| 2805 | - <div class="vbo-modal-overlay-content-footer-right"> | |
| 2806 | - <div id="vbo-modal-footer-sms" style="display: none;"> | |
| 2807 | - <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> | |
| 3908 | +<div class="vbo-bookingdet-send-tplmessage-helper" style="display: none;"> | |
| 3909 | + <div class="vbo-bookingdet-send-tplmessage-wrap"> | |
| 3910 | + <div class="vbo-admin-container vbo-admin-container-full vbo-admin-container-compact"> | |
| 3911 | + <div class="vbo-params-wrap"> | |
| 3912 | + <div class="vbo-params-container"> | |
| 3913 | + <div class="vbo-params-block"> | |
| 3914 | + <?php | |
| 3915 | + echo VBOParamsRendering::getInstance( | |
| 3916 | + [ | |
| 3917 | + 'ma_identifier' => [ | |
| 3918 | + 'type' => 'elements', | |
| 3919 | + 'label' => JText::translate('VBO_MESSAGE_TEMPLATE'), | |
| 3920 | + 'asset_options' => [ | |
| 3921 | + 'placeholder' => JText::translate('VBO_MESSAGE_TEMPLATE'), | |
| 3922 | + 'allowClear' => false, | |
| 3923 | + ], | |
| 3924 | + 'inline' => false, | |
| 3925 | + 'wrapdivcls' => 'vbo-singleselect-inline-elems-wrap vbo-singleselect-inline-small-icons', | |
| 3926 | + 'style_selection' => true, | |
| 3927 | + 'attributes' => [ | |
| 3928 | + 'data-element' => 'message-template', | |
| 3929 | + ], | |
| 3930 | + 'elements' => array_map(function($maConfig) { | |
| 3931 | + if (!empty($maConfig['channel_logo'])) { | |
| 3932 | + $messTplName = sprintf('%s (%s)', $maConfig['name'], $maConfig['lang']); | |
| 3933 | + } else { | |
| 3934 | + $messTplName = sprintf('%s - %s (%s)', $maConfig['channel_name'], $maConfig['name'], $maConfig['lang']); | |
| 3935 | + } | |
| 3936 | + return array_filter([ | |
| 3937 | + 'id' => $maConfig['identifier'], | |
| 3938 | + 'name' => $messTplName, | |
| 3939 | + 'img_uri' => ($maConfig['channel_logo'] ?? '') ?: null, | |
| 3940 | + ]); | |
| 3941 | + }, $messagingAccountConfigurations), | |
| 3942 | + ], | |
| 3943 | + ], | |
| 3944 | + [] | |
| 3945 | + )->setInputName('send_ma_tpl')->getHtml(); | |
| 3946 | + ?> | |
| 3947 | + <div class="vbo-param-container"> | |
| 3948 | + <div class="vbo-param-label"><?php echo JText::translate('VBOPREVIEW'); ?></div> | |
| 3949 | + <div class="vbo-param-setting"> | |
| 3950 | + <div class="vbo-ma-send-tplmessage-preview"></div> | |
| 3951 | + </div> | |
| 3952 | + </div> | |
| 3953 | + </div> | |
| 2808 | 3954 | </div> |
| 2809 | - <div id="vbo-modal-footer-email" style="display: none;"> | |
| 2810 | - <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> | |
| 2811 | - </div> | |
| 2812 | 3955 | </div> |
| 2813 | 3956 | </div> |
| 2814 | - | |
| 2815 | 3957 | </div> |
| 2816 | 3958 | </div> |
| 2817 | 3959 | |
| 2818 | 3960 | <script type="text/javascript"> |
| 2819 | -var vbo_overlay_on = false; | |
| 2820 | 3961 | var vbo_print_only = false; |
| 2821 | -if (jQuery.isFunction(jQuery.fn.tooltip)) { | |
| 3962 | +if (typeof jQuery.fn.tooltip === 'function') { | |
| 2822 | 3963 | jQuery(".hasTooltip").tooltip(); |
| 2823 | 3964 | } |
| 2824 | -function vboToggleSendSMS() { | |
| 3965 | +function vboDisplaySendSMS() { | |
| 2825 | 3966 | var cur_phone = jQuery("#smstophone").val(); |
| 2826 | 3967 | var phone_set = jQuery("#custphone").trigger('vboupdatephonenumber').val(); |
| 2827 | 3968 | if (phone_set.length && phone_set != cur_phone) { |
| 2828 | 3969 | jQuery("#smstophone").val(phone_set); |
| 2829 | - jQuery("#smstophone-lbl").text(phone_set); | |
| 2830 | 3970 | } |
| 2831 | 3971 | |
| 2832 | - // toggle email/sms contents | |
| 2833 | - jQuery("#vbo-overlay-email-cont, #vbo-modal-footer-email").hide(); | |
| 2834 | - jQuery("#vbo-overlay-sms-cont, #vbo-modal-footer-sms").show(); | |
| 2835 | - var use_modal_title = jQuery("#vbo-overlay-sms-cont").find('h4').first().html(); | |
| 2836 | - jQuery('.vbo-modal-overlay-content-sms-email-head').find('h3').find('span').first().html(use_modal_title); | |
| 3972 | + // define the modal cancel button | |
| 3973 | + let cancel_btn = jQuery('<button></button>') | |
| 3974 | + .attr('type', 'button') | |
| 3975 | + .addClass('btn') | |
| 3976 | + .text(Joomla.JText._('VBANNULLA')) | |
| 3977 | + .on('click', function() { | |
| 3978 | + VBOCore.emitEvent('vbo-editorder-send-sms-dismiss'); | |
| 3979 | + }); | |
| 2837 | 3980 | |
| 2838 | - jQuery(".vbo-modal-overlay-block-sms-email").fadeToggle(400, function() { | |
| 2839 | - if (jQuery(".vbo-modal-overlay-block-sms-email").is(":visible")) { | |
| 2840 | - vbo_overlay_on = true; | |
| 2841 | - } else { | |
| 2842 | - vbo_overlay_on = false; | |
| 2843 | - } | |
| 3981 | + // display modal for email/sms contents | |
| 3982 | + let modal_body = VBOCore.displayModal({ | |
| 3983 | + suffix: 'editorder-send-sms', | |
| 3984 | + extra_class: 'vbo-modal-large', | |
| 3985 | + lock_scroll: true, | |
| 3986 | + title: Joomla.JText._('VBSENDSMSACTION') + ': ' + (phone_set && phone_set != cur_phone ? phone_set : cur_phone), | |
| 3987 | + footer_left: cancel_btn, | |
| 3988 | + footer_right: jQuery('#vbo-modal-footer-sms').find('button').clone(), | |
| 3989 | + loading_event: 'vbo-editorder-send-sms-loading', | |
| 3990 | + dismiss_event: 'vbo-editorder-send-sms-dismiss', | |
| 3991 | + onDismiss: () => { | |
| 3992 | + jQuery('.vbo-editorder-sms-send-wrap').appendTo('.vbo-editorder-sms-email-send-helper'); | |
| 3993 | + }, | |
| 2844 | 3994 | }); |
| 3995 | + | |
| 3996 | + jQuery('.vbo-editorder-sms-send-wrap').appendTo(modal_body); | |
| 2845 | 3997 | } |
| 2846 | -function vboToggleSendEmail() { | |
| 3998 | +function vboDisplaySendEmail() { | |
| 2847 | 3999 | var cur_email = jQuery("#emailto").val(); |
| 2848 | 4000 | var email_set = jQuery("#custmail").val(); |
| 2849 | 4001 | if (email_set.length && email_set != cur_email) { |
| 2850 | 4002 | jQuery("#emailto").val(email_set); |
| 2851 | - jQuery("#emailto-lbl").text(email_set); | |
| 2852 | 4003 | } |
| 2853 | 4004 | |
| 2854 | - // toggle email/sms contents | |
| 2855 | - jQuery("#vbo-overlay-sms-cont, #vbo-modal-footer-sms").hide(); | |
| 2856 | - jQuery("#vbo-overlay-email-cont, #vbo-modal-footer-email").show(); | |
| 2857 | - var use_modal_title = jQuery("#vbo-overlay-email-cont").find('h4').first().html(); | |
| 2858 | - jQuery('.vbo-modal-overlay-content-sms-email-head').find('h3').find('span').first().html(use_modal_title); | |
| 4005 | + // define the modal cancel button | |
| 4006 | + let cancel_btn = jQuery('<button></button>') | |
| 4007 | + .attr('type', 'button') | |
| 4008 | + .addClass('btn') | |
| 4009 | + .text(Joomla.JText._('VBANNULLA')) | |
| 4010 | + .on('click', function() { | |
| 4011 | + VBOCore.emitEvent('vbo-editorder-send-email-dismiss'); | |
| 4012 | + }); | |
| 2859 | 4013 | |
| 2860 | - jQuery(".vbo-modal-overlay-block-sms-email").fadeToggle(400, function() { | |
| 2861 | - if (jQuery(".vbo-modal-overlay-block-sms-email").is(":visible")) { | |
| 2862 | - vbo_overlay_on = true; | |
| 2863 | - } else { | |
| 2864 | - vbo_overlay_on = false; | |
| 2865 | - } | |
| 4014 | + // display modal for email/sms contents | |
| 4015 | + let modal_body = VBOCore.displayModal({ | |
| 4016 | + suffix: 'editorder-send-email', | |
| 4017 | + extra_class: 'vbo-modal-large', | |
| 4018 | + lock_scroll: true, | |
| 4019 | + title: Joomla.JText._('VBSENDEMAILACTION') + ': ' + (email_set && email_set != cur_email ? email_set : cur_email), | |
| 4020 | + footer_left: cancel_btn, | |
| 4021 | + footer_right: jQuery('#vbo-modal-footer-email').find('button').clone(), | |
| 4022 | + loading_event: 'vbo-editorder-send-email-loading', | |
| 4023 | + dismiss_event: 'vbo-editorder-send-email-dismiss', | |
| 4024 | + onDismiss: () => { | |
| 4025 | + jQuery('.vbo-editorder-email-send-wrap').appendTo('.vbo-editorder-sms-email-send-helper'); | |
| 4026 | + }, | |
| 2866 | 4027 | }); |
| 4028 | + | |
| 4029 | + jQuery('.vbo-editorder-email-send-wrap').appendTo(modal_body); | |
| 2867 | 4030 | } |
| 2868 | 4031 | function vboKeyupEmail(event) { |
| 2869 | 4032 | if (event.key && event.key == 'Enter') { |
| 2870 | 4033 | event.preventDefault(); |
| @@ -2901,8 +4064,12 @@ | ||
| 2901 | 4064 | } |
| 2902 | 4065 | // reload the page to display the new information about the booking just modified |
| 2903 | 4066 | location.reload(); |
| 2904 | 4067 | }); |
| 4068 | + // register click event for the button to see the quote details | |
| 4069 | + document.querySelector('.vbo-quote-details-btn')?.addEventListener('click', (e) => { | |
| 4070 | + VBOCore.handleDisplayWidgetNotification({widget_id: 'quotes'}, {bid: <?php echo $row['id']; ?>}); | |
| 4071 | + }); | |
| 2905 | 4072 | // remove overbooking flag |
| 2906 | 4073 | jQuery('.vbo-label-overbooking').on('click', function() { |
| 2907 | 4074 | if (confirm(Joomla.JText._('VBO_CONF_RM_OVERBOOKING_FLAG'))) { |
| 2908 | 4075 | VBOCore.doAjax( |
| @@ -2998,24 +4165,8 @@ | ||
| 2998 | 4165 | return; |
| 2999 | 4166 | } |
| 3000 | 4167 | }); |
| 3001 | 4168 | // Search customer - End |
| 3002 | - jQuery(document).mouseup(function(e) { | |
| 3003 | - if (!vbo_overlay_on) { | |
| 3004 | - return false; | |
| 3005 | - } | |
| 3006 | - var vbo_overlay_cont = jQuery(".vbo-modal-overlay-content-sms-email"); | |
| 3007 | - if (!vbo_overlay_cont.is(e.target) && vbo_overlay_cont.has(e.target).length === 0 && !jQuery(e.target).is('svg')) { | |
| 3008 | - jQuery(".vbo-modal-overlay-block-sms-email").fadeOut(); | |
| 3009 | - vbo_overlay_on = false; | |
| 3010 | - } | |
| 3011 | - }); | |
| 3012 | - jQuery(document).keyup(function(e) { | |
| 3013 | - if (e.keyCode == 27 && vbo_overlay_on) { | |
| 3014 | - jQuery(".vbo-modal-overlay-block-sms-email").fadeOut(); | |
| 3015 | - vbo_overlay_on = false; | |
| 3016 | - } | |
| 3017 | - }); | |
| 3018 | 4169 | jQuery(".vbo-bookingdet-tab").click(function() { |
| 3019 | 4170 | var newtabrel = jQuery(this).attr('data-vbotab'); |
| 3020 | 4171 | var oldtabrel = jQuery(".vbo-bookingdet-tab-active").attr('data-vbotab'); |
| 3021 | 4172 | if (newtabrel == oldtabrel) { |
| @@ -3146,8 +4297,242 @@ | ||
| 3146 | 4297 | idorder: '<?php echo $row['id']; ?>', |
| 3147 | 4298 | } |
| 3148 | 4299 | }); |
| 3149 | 4300 | |
| 4301 | + // register click event on the booking task(s) | |
| 4302 | + document.querySelectorAll('.vbo-bookingdet-task-details[data-task-id]').forEach((task) => { | |
| 4303 | + const taskId = task.getAttribute('data-task-id'); | |
| 4304 | + task.addEventListener('click', (e) => { | |
| 4305 | + e.stopPropagation(); | |
| 4306 | + // define the modal cancel button | |
| 4307 | + let cancel_btn = jQuery('<button></button>') | |
| 4308 | + .attr('type', 'button') | |
| 4309 | + .addClass('btn') | |
| 4310 | + .text(Joomla.JText._('VBOCLOSE')) | |
| 4311 | + .on('click', () => { | |
| 4312 | + VBOCore.emitEvent('vbo-tm-edittask-dismiss'); | |
| 4313 | + }); | |
| 4314 | + | |
| 4315 | + // define the modal save button | |
| 4316 | + let save_btn = jQuery('<button></button>') | |
| 4317 | + .attr('type', 'button') | |
| 4318 | + .addClass('btn btn-success') | |
| 4319 | + .text(Joomla.JText._('VBSAVE')) | |
| 4320 | + .on('click', function() { | |
| 4321 | + // disable button to prevent double submissions | |
| 4322 | + let submit_btn = jQuery(this); | |
| 4323 | + submit_btn.prop('disabled', true); | |
| 4324 | + | |
| 4325 | + // start loading animation | |
| 4326 | + VBOCore.emitEvent('vbo-tm-edittask-loading'); | |
| 4327 | + | |
| 4328 | + // get form data | |
| 4329 | + const taskForm = new FormData(document.querySelector('#vbo-tm-task-manage-form')); | |
| 4330 | + | |
| 4331 | + // build query parameters for the request | |
| 4332 | + let qpRequest = new URLSearchParams(taskForm); | |
| 4333 | + | |
| 4334 | + // make sure the request always includes the assignees query parameter, even if the list is empty | |
| 4335 | + if (!qpRequest.has('data[assignees][]')) { | |
| 4336 | + qpRequest.append('data[assignees][]', []); | |
| 4337 | + } | |
| 4338 | + | |
| 4339 | + // make sure the request always includes the tags query parameter, even if the list is empty | |
| 4340 | + if (!qpRequest.has('data[tags][]')) { | |
| 4341 | + qpRequest.append('data[tags][]', []); | |
| 4342 | + } | |
| 4343 | + | |
| 4344 | + // make the request | |
| 4345 | + VBOCore.doAjax( | |
| 4346 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.updateTask'); ?>", | |
| 4347 | + qpRequest.toString(), | |
| 4348 | + (resp) => { | |
| 4349 | + // dismiss the modal on success | |
| 4350 | + VBOCore.emitEvent('vbo-tm-edittask-dismiss'); | |
| 4351 | + | |
| 4352 | + // reload the page | |
| 4353 | + location.reload(); | |
| 4354 | + }, | |
| 4355 | + (error) => { | |
| 4356 | + // display error message | |
| 4357 | + alert(error.responseText); | |
| 4358 | + | |
| 4359 | + // re-enable submit button | |
| 4360 | + submit_btn.prop('disabled', false); | |
| 4361 | + | |
| 4362 | + // stop loading | |
| 4363 | + VBOCore.emitEvent('vbo-tm-edittask-loading'); | |
| 4364 | + } | |
| 4365 | + ); | |
| 4366 | + }); | |
| 4367 | + | |
| 4368 | + // display modal | |
| 4369 | + let modalBody = VBOCore.displayModal({ | |
| 4370 | + suffix: 'tm_edittask_modal', | |
| 4371 | + title: <?php echo json_encode(JText::translate('VBO_TASK')); ?> + ' #' + taskId, | |
| 4372 | + extra_class: 'vbo-modal-rounded vbo-modal-taller vbo-modal-large', | |
| 4373 | + body_prepend: true, | |
| 4374 | + lock_scroll: true, | |
| 4375 | + escape_dismiss: false, | |
| 4376 | + footer_left: cancel_btn, | |
| 4377 | + footer_right: save_btn, | |
| 4378 | + loading_event: 'vbo-tm-edittask-loading', | |
| 4379 | + dismiss_event: 'vbo-tm-edittask-dismiss', | |
| 4380 | + }); | |
| 4381 | + | |
| 4382 | + // start loading animation | |
| 4383 | + VBOCore.emitEvent('vbo-tm-edittask-loading'); | |
| 4384 | + | |
| 4385 | + // make the request | |
| 4386 | + VBOCore.doAjax( | |
| 4387 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=taskmanager.renderLayout'); ?>", | |
| 4388 | + { | |
| 4389 | + type: 'tasks.managetask', | |
| 4390 | + data: { | |
| 4391 | + task_id: taskId, | |
| 4392 | + form_id: 'vbo-tm-task-manage-form', | |
| 4393 | + }, | |
| 4394 | + }, | |
| 4395 | + (resp) => { | |
| 4396 | + // stop loading | |
| 4397 | + VBOCore.emitEvent('vbo-tm-edittask-loading'); | |
| 4398 | + | |
| 4399 | + try { | |
| 4400 | + // decode the response (if needed), and append the content to the modal body | |
| 4401 | + let obj_res = typeof resp === 'string' ? JSON.parse(resp) : resp; | |
| 4402 | + modalBody.append(obj_res['html']); | |
| 4403 | + } catch (err) { | |
| 4404 | + console.error('Error decoding the response', err, resp); | |
| 4405 | + } | |
| 4406 | + }, | |
| 4407 | + (error) => { | |
| 4408 | + // display error message | |
| 4409 | + alert(error.responseText); | |
| 4410 | + | |
| 4411 | + // stop loading | |
| 4412 | + VBOCore.emitEvent('vbo-tm-edittask-loading'); | |
| 4413 | + } | |
| 4414 | + ); | |
| 4415 | + }); | |
| 4416 | + }); | |
| 4417 | + | |
| 4418 | + // register click event to copy the OTA booking ID | |
| 4419 | + const otaBidEl = document.querySelector('.vbo-reservation-copy-otabid'); | |
| 4420 | + if (otaBidEl) { | |
| 4421 | + otaBidEl.addEventListener('click', () => { | |
| 4422 | + let copyEl = document.querySelector('textarea.vbo-textarea-copyable[data-copy="otabid"]'); | |
| 4423 | + VBOCore.copyToClipboard(copyEl).then((success) => { | |
| 4424 | + otaBidEl.setAttribute('data-tooltiptext', <?php echo json_encode(JText::translate('VBO_COPIED') . '!'); ?>); | |
| 4425 | + }).catch((err) => { | |
| 4426 | + // do nothing | |
| 4427 | + }); | |
| 4428 | + }); | |
| 4429 | + } | |
| 4430 | + | |
| 4431 | + // register events for sending a message template through a messaging account configuration | |
| 4432 | + const messagingAccountsData = <?php echo json_encode($messagingAccountConfigurations); ?>; | |
| 4433 | + const sendTplMessBtn = document.querySelector('.vbo-bookingdet-send-tplmessage-btn'); | |
| 4434 | + const sendTplMessContWrap = document.querySelector('.vbo-bookingdet-send-tplmessage-wrap'); | |
| 4435 | + jQuery(sendTplMessContWrap).find('select[data-element="message-template"]').on('change', function() { | |
| 4436 | + let maIdentifier = this.value; | |
| 4437 | + let previewEl = sendTplMessContWrap.querySelector('.vbo-ma-send-tplmessage-preview'); | |
| 4438 | + previewEl.innerHTML = ''; | |
| 4439 | + if (maIdentifier) { | |
| 4440 | + messagingAccountsData.forEach((maData) => { | |
| 4441 | + if (maData?.identifier == maIdentifier) { | |
| 4442 | + // update preview content | |
| 4443 | + previewEl.innerHTML = maData?.preview_html || ''; | |
| 4444 | + } | |
| 4445 | + }); | |
| 4446 | + } | |
| 4447 | + }); | |
| 4448 | + if (sendTplMessBtn) { | |
| 4449 | + sendTplMessBtn.addEventListener('click', () => { | |
| 4450 | + let cancelBtn = document.createElement('button'); | |
| 4451 | + cancelBtn.setAttribute('type', 'button'); | |
| 4452 | + cancelBtn.classList.add('btn'); | |
| 4453 | + cancelBtn.textContent = <?php echo json_encode(JText::translate('VBANNULLA')); ?>; | |
| 4454 | + cancelBtn.addEventListener('click', () => { | |
| 4455 | + VBOCore.emitEvent('vbo-send-tplmessage-dismiss'); | |
| 4456 | + }); | |
| 4457 | + | |
| 4458 | + let confirmBtn = document.createElement('button'); | |
| 4459 | + confirmBtn.setAttribute('type', 'button'); | |
| 4460 | + confirmBtn.classList.add('btn', 'btn-primary'); | |
| 4461 | + confirmBtn.innerHTML = '<?php VikBookingIcons::e('paper-plane'); ?> ' + <?php echo json_encode(JText::translate('VBO_SEND_MESSAGE')); ?>; | |
| 4462 | + confirmBtn.addEventListener('click', () => { | |
| 4463 | + // get message template identifier data | |
| 4464 | + let tplIdentifier = sendTplMessContWrap.querySelector('select[data-element="message-template"]')?.value; | |
| 4465 | + if (!tplIdentifier) { | |
| 4466 | + alert('Invalid message template'); | |
| 4467 | + return; | |
| 4468 | + } | |
| 4469 | + | |
| 4470 | + // obtain selected template details | |
| 4471 | + let tplIdentifierParts = tplIdentifier.split(':'); | |
| 4472 | + | |
| 4473 | + // start loading | |
| 4474 | + VBOCore.emitEvent('vbo-send-tplmessage-loading'); | |
| 4475 | + confirmBtn.disabled = true; | |
| 4476 | + | |
| 4477 | + // make the request | |
| 4478 | + VBOCore.doAjax( | |
| 4479 | + "<?php echo VikBooking::ajaxUrl('index.php?option=com_vikbooking&task=messaging.sendMessageTemplate'); ?>", | |
| 4480 | + { | |
| 4481 | + account_id: tplIdentifierParts[0], | |
| 4482 | + phone_id: tplIdentifierParts[1], | |
| 4483 | + config_id: tplIdentifierParts[2], | |
| 4484 | + booking_id: <?php echo $this->row['id']; ?>, | |
| 4485 | + }, | |
| 4486 | + (resp) => { | |
| 4487 | + // dismiss modal on success | |
| 4488 | + VBOCore.emitEvent('vbo-send-tplmessage-dismiss'); | |
| 4489 | + | |
| 4490 | + // display success message | |
| 4491 | + VBOToast.enqueue(new VBOToastMessage({ | |
| 4492 | + body: <?php echo json_encode(JText::translate('VBSENDEMAILOK')); ?>, | |
| 4493 | + icon: '<?php echo VikBookingIcons::i('check-circle'); ?>', | |
| 4494 | + status: VBOToast.SUCCESS_STATUS, | |
| 4495 | + action: () => { | |
| 4496 | + VBOToast.dispose(true); | |
| 4497 | + }, | |
| 4498 | + })); | |
| 4499 | + | |
| 4500 | + // reload the page (just for the new history event) | |
| 4501 | + location.reload(); | |
| 4502 | + }, | |
| 4503 | + (error) => { | |
| 4504 | + // display error message | |
| 4505 | + alert(error.responseText); | |
| 4506 | + | |
| 4507 | + // stop loading | |
| 4508 | + VBOCore.emitEvent('vbo-send-tplmessage-loading'); | |
| 4509 | + confirmBtn.disabled = false; | |
| 4510 | + } | |
| 4511 | + ); | |
| 4512 | + }); | |
| 4513 | + | |
| 4514 | + let modalBody = VBOCore.displayModal({ | |
| 4515 | + suffix: 'vbo-send-tplmessage', | |
| 4516 | + extra_class: 'vbo-modal-rounded', | |
| 4517 | + title: <?php echo json_encode(JText::translate('VBO_SEND_MESSAGE')); ?>, | |
| 4518 | + footer_left: cancelBtn, | |
| 4519 | + footer_right: confirmBtn, | |
| 4520 | + draggable: true, | |
| 4521 | + lock_scroll: true, | |
| 4522 | + dismiss_event: 'vbo-send-tplmessage-dismiss', | |
| 4523 | + loading_event: 'vbo-send-tplmessage-loading', | |
| 4524 | + onDismiss: () => { | |
| 4525 | + document.querySelector('.vbo-bookingdet-send-tplmessage-helper').append( | |
| 4526 | + sendTplMessContWrap | |
| 4527 | + ); | |
| 4528 | + }, | |
| 4529 | + }); | |
| 4530 | + | |
| 4531 | + (modalBody[0] || modalBody).append(sendTplMessContWrap); | |
| 4532 | + }); | |
| 4533 | + } | |
| 4534 | + | |
| 3150 | 4535 | }); |
| 3151 | 4536 | var cur_emtpl = <?php echo json_encode($cur_emtpl); ?>; |
| 3152 | 4537 | function vboLoadEmailTpl(tplind) { |
| 3153 | 4538 | if (!(tplind.length > 0)) { |
| @@ -3174,9 +4559,9 @@ | ||
| 3174 | 4559 | <?php |
| 3175 | 4560 | $pcustomemail = VikRequest::getInt('customemail', '', 'request'); |
| 3176 | 4561 | if ($pcustomemail > 0) { |
| 3177 | 4562 | ?> |
| 3178 | - vboToggleSendEmail(); | |
| 4563 | + vboDisplaySendEmail(); | |
| 3179 | 4564 | <?php |
| 3180 | 4565 | } |
| 3181 | 4566 | if ($printreceipt) { |
| 3182 | 4567 | ?> |