diff --git a/classes/pdf/HTMLTemplateInvoice.php b/classes/pdf/HTMLTemplateInvoice.php
index 7c9494d8b..70284fd87 100644
--- a/classes/pdf/HTMLTemplateInvoice.php
+++ b/classes/pdf/HTMLTemplateInvoice.php
@@ -169,7 +169,11 @@ class HTMLTemplateInvoiceCore extends HTMLTemplate
$order_detail['unit_price_tax_excl_before_specific_price'] = $order_detail['unit_price_tax_excl_including_ecotax'] + $order_detail['reduction_amount_tax_excl'];
} elseif ($order_detail['reduction_percent'] > 0) {
$has_discount = true;
- $order_detail['unit_price_tax_excl_before_specific_price'] = (100 * $order_detail['unit_price_tax_excl_including_ecotax']) / (100 - $order_detail['reduction_percent']);
+ if ($order_detail['reduction_percent'] >= 100) {
+ $order_detail['unit_price_tax_excl_before_specific_price'] = $order_detail['original_product_price'];
+ } else {
+ $order_detail['unit_price_tax_excl_before_specific_price'] = (100 * $order_detail['unit_price_tax_excl_including_ecotax']) / (100 - $order_detail['reduction_percent']);
+ }
}
// Set tax_code
diff --git a/controllers/front/GuestTrackingController.php b/controllers/front/GuestTrackingController.php
index f8be455c6..cf5007d66 100644
--- a/controllers/front/GuestTrackingController.php
+++ b/controllers/front/GuestTrackingController.php
@@ -252,7 +252,6 @@ class GuestTrackingControllerCore extends FrontController
if ($orderProducts = $order->getProducts()) {
$total_convenience_fee_te = 0;
$total_convenience_fee_ti = 0;
- $total_tourism_tax = OrderTaxDetail::getOrderTourismTaxTotal($idOrder);
$objOrderReturn = new OrderReturn();
$refundReqBookings = $objOrderReturn->getOrderRefundRequestedBookings($order->id, 0, 1);
@@ -536,6 +535,7 @@ class GuestTrackingControllerCore extends FrontController
// set order specific values
$order->total_convenience_fee_ti = $total_convenience_fee_ti;
$order->total_convenience_fee_te = $total_convenience_fee_te;
+ $order->total_tourism_tax = OrderTaxDetail::getOrderTourismTaxTotal($idOrder);
$order->any_back_order = $anyBackOrder;
$order->shw_bo_msg = Configuration::get('WK_SHOW_MSG_ON_BO');
$order->back_ord_msg = Configuration::get('WK_BO_MESSAGE');
@@ -567,7 +567,6 @@ class GuestTrackingControllerCore extends FrontController
'use_tax' => Configuration::get('PS_TAX'),
'guestInformations' => (array)$customer,
'view_on_map' => Configuration::get('WK_GOOGLE_ACTIVE_MAP'),
- 'total_tourism_tax' => isset($total_tourism_tax) ? $total_tourism_tax : 0,
'show_tourism_tax_separately' => (bool) Configuration::get('QLO_TOURISM_TAX_SHOW_SEPARATE'),
));
}
diff --git a/install-dev/models/install.php b/install-dev/models/install.php
index d9dabfca6..6f3fd3265 100644
--- a/install-dev/models/install.php
+++ b/install-dev/models/install.php
@@ -721,7 +721,7 @@ class InstallModelInstall extends InstallAbstractModel
'qlostatsserviceproducts',
'blockcart',
'blockuserinfo',
- 'qlochannelmanagerconnector',
+ 'qlocmconnector',
'qlogooglehotelconnector'
);
}
diff --git a/modules/blockcart/blockcart.tpl b/modules/blockcart/blockcart.tpl
index 347cab3f9..f2d03ddae 100644
--- a/modules/blockcart/blockcart.tpl
+++ b/modules/blockcart/blockcart.tpl
@@ -161,7 +161,7 @@
{/block}
{block name='blockcart_shopping_cart_total_convenience_fee'}
{if isset($total_convenience_fee)}
-
+
{l s='Convenience Fees' mod='blockcart'}
{if $use_taxes && $display_tax_label}
diff --git a/modules/hotelreservationsystem/classes/HotelBookingDetail.php b/modules/hotelreservationsystem/classes/HotelBookingDetail.php
index b4ae5b8ea..2672d223a 100644
--- a/modules/hotelreservationsystem/classes/HotelBookingDetail.php
+++ b/modules/hotelreservationsystem/classes/HotelBookingDetail.php
@@ -4423,6 +4423,7 @@ class HotelBookingDetail extends ObjectModel
*/
public static function getPaymentMethodStats(array $params)
{
+ $paymentMethod = isset($params['payment_method']) ? pSQL($params['payment_method']) : '';
$dateFrom = pSQL($params['date_from']);
$dateTo = pSQL(isset($params['date_to']) ? $params['date_to'] : $params['date_from']);
$idsHotel = isset($params['ids_hotel']) ? $params['ids_hotel'] : (isset($params['id_hotel']) ? $params['id_hotel'] : false);
@@ -4441,12 +4442,32 @@ class HotelBookingDetail extends ObjectModel
AND hbd.`date_add` BETWEEN "'.$dateFrom.' 00:00:00" AND "'.$dateTo.' 23:59:59"'
.($idCustomer ? ' AND hbd.`id_customer` = '.$idCustomer : '')
.($bookingType ? ' AND hbd.`booking_type` = '.$bookingType : '')
+ .($paymentMethod ? ' AND o.`payment` = \''.$paymentMethod.'\'' : '')
.HotelBranchInformation::addHotelRestriction($idsHotel, 'hbd').'
GROUP BY o.`payment`, o.`module`
ORDER BY revenue_incl DESC'
);
}
+ /**
+ * Distinct payment method names stored on valid hotel orders, used to filter the Payment Methods report.
+ *
+ * @param int|false $idHotel
+ * @return array rows: payment_method
+ */
+ public static function getDistinctOrderPaymentMethods($idHotel = false)
+ {
+ return Db::getInstance(_PS_USE_SQL_SLAVE_)->executeS(
+ 'SELECT DISTINCT o.`payment` AS payment_method
+ FROM `'._DB_PREFIX_.'htl_booking_detail` hbd
+ INNER JOIN `'._DB_PREFIX_.'orders` o ON (o.`id_order` = hbd.`id_order` AND o.`valid` = 1)
+ WHERE hbd.`id_status` != '.self::STATUS_CANCELLED.' AND o.`payment` != ""'
+ .HotelBranchInformation::addHotelRestriction($idHotel, 'hbd').'
+ ORDER BY o.`payment`'
+ );
+ }
+
+
/**
* Tax breakdown per booking line for the Tax Report.
* Delegates to ServiceProductOrderDetail::getTaxBreakdown() for service revenue.
diff --git a/modules/qlocmconnector/upgrade/upgrade-5.0.5.php b/modules/qlocmconnector/upgrade/upgrade-7.0.0.php
similarity index 92%
rename from modules/qlocmconnector/upgrade/upgrade-5.0.5.php
rename to modules/qlocmconnector/upgrade/upgrade-7.0.0.php
index 8b7b463b9..24f0768a3 100644
--- a/modules/qlocmconnector/upgrade/upgrade-5.0.5.php
+++ b/modules/qlocmconnector/upgrade/upgrade-7.0.0.php
@@ -25,9 +25,9 @@
if (!defined('_PS_VERSION_'))
exit;
-function upgrade_module_5_0_5($module)
+function upgrade_module_7_0_0($module)
{
- $objCMConnector = new UpgradeQloCMConnector505($module);
+ $objCMConnector = new UpgradeQloCMConnector700($module);
return (
$objCMConnector->registerHooks()
&& $objCMConnector->removeOldModule()
@@ -35,7 +35,7 @@ function upgrade_module_5_0_5($module)
);
}
-class UpgradeQloCMConnector505{
+class UpgradeQloCMConnector700{
public function __construct($module)
{
$this->module = $module;
diff --git a/modules/qloduitkupayment/controllers/front/return.php b/modules/qloduitkupayment/controllers/front/return.php
index 0f9fbbd2d..92d11c860 100644
--- a/modules/qloduitkupayment/controllers/front/return.php
+++ b/modules/qloduitkupayment/controllers/front/return.php
@@ -106,31 +106,40 @@ class QloDuitkuPaymentReturnModuleFrontController extends ModuleFrontController
$this->module->logger->log('After Cart Validation in return.', FileLogger::DEBUG);
$objDuitkuTransaction->addCartLock((int) $idCart);
if (!$res) {
- $objDuitkuTransaction->save();
+ $objDuitkuTransaction->save();
}
- if ($this->module->validateOrder(
- (int) $idCart,
- $orderStatus,
- $cartAmount,
- $this->module->l('Duitku Payment', 'return'),
- null,
- $extraVars,
- (int) $id_currency,
- false,
- $objCustomer->secure_key
- )) {
+ $statusResponse = $this->module->checkDuitkuTransactionStatus($merchantOrderId);
+ $statusCode = isset($statusResponse['response']['statusCode']) ? $statusResponse['response']['statusCode'] : null;
- $this->module->logger->log('Return Process Order created.', FileLogger::DEBUG);
+ if ($statusResponse['status'] === true && ($statusCode == '00' || $statusCode == '01')) {
+ if ($this->module->validateOrder(
+ (int) $idCart,
+ $orderStatus,
+ $cartAmount,
+ $this->module->l('Duitku Payment', 'return'),
+ null,
+ $extraVars,
+ (int) $id_currency,
+ false,
+ $objCustomer->secure_key
+ )) {
- $url = $this->context->link->getPageLink('order-confirmation', true, null, [
- 'id_cart' => $idCart,
- 'id_module' => $this->module->id,
- 'id_order' => Order::getOrderByCartId($idCart),
- 'success' => 1,
- 'key' => $objCustomer->secure_key,
- ]);
- Tools::redirect($url);
+ $this->module->logger->log('Return Process Order created.', FileLogger::DEBUG);
+
+ $url = $this->context->link->getPageLink('order-confirmation', true, null, [
+ 'id_cart' => $idCart,
+ 'id_module' => $this->module->id,
+ 'id_order' => Order::getOrderByCartId($idCart),
+ 'success' => 1,
+ 'key' => $objCustomer->secure_key,
+ ]);
+ Tools::redirect($url);
+ }
+ } else {
+ $this->module->logger->log('Duitku could not confirm transaction for merchantOrderId ' . $merchantOrderId, FileLogger::DEBUG);
+ $objDuitkuTransaction->removeCartLock($idCart);
+ Tools::redirect($this->context->link->getModuleLink('qloduitkupayment', 'error') . '?validation_err=1&id=' . $merchantOrderId);
}
}
diff --git a/modules/qloduitkupayment/qloduitkupayment.php b/modules/qloduitkupayment/qloduitkupayment.php
index e53ca05e1..f420061ee 100644
--- a/modules/qloduitkupayment/qloduitkupayment.php
+++ b/modules/qloduitkupayment/qloduitkupayment.php
@@ -446,6 +446,34 @@ class QloDuitkuPayment extends PaymentModule
);
}
+ /**
+ * Confirm a transaction's real status with Duitku's own server-to-server API, rather
+ * than trusting the unsigned browser return redirect. Must be called at most once per
+ * return hit - Duitku rate-limits repeated calls to this endpoint.
+ *
+ * @param string $merchantOrderId
+ *
+ * @return array
+ */
+ public function checkDuitkuTransactionStatus($merchantOrderId)
+ {
+ $merchantCode = Configuration::get('QDP_DUITKU_PAYMENT_MERCHANT_CODE');
+ $apiKey = Configuration::get('QDP_DUITKU_PAYMENT_API_KEY');
+ $signature = hash_hmac('sha256', $merchantCode . $merchantOrderId, $apiKey);
+
+ $params = array(
+ 'merchantCode' => $merchantCode,
+ 'merchantOrderId' => $merchantOrderId,
+ 'signature' => $signature,
+ );
+
+ return QdpDuitkuServiceRequest::makeRequest(
+ 'transactionStatus',
+ QdpDuitkuTransaction::QDP_CURL_REQUEST_TYPE_POST,
+ $params
+ );
+ }
+
private function getCustomerPhone($customer, $addressId)
{
if (!empty($customer->phone)) {
diff --git a/modules/qlohotelreports/qlohotelreports.php b/modules/qlohotelreports/qlohotelreports.php
index 9febdd8af..489af99ce 100644
--- a/modules/qlohotelreports/qlohotelreports.php
+++ b/modules/qlohotelreports/qlohotelreports.php
@@ -760,17 +760,28 @@ class QloHotelReports extends Module
if ($report === 'source' || $report === 'payment-method') {
$bookingSource = pSQL(Tools::getValue('booking_source', ''));
+ $paymentMethod = pSQL(Tools::getValue('payment_method', ''));
$filterBaseUrl = $baseUrl . '&tab=' . $report
- . ($idHotel ? '&id_hotel=' . $idHotel : '')
- . ($bookingSource ? '&booking_source=' . $bookingSource : '');
+ . ($idHotel ? '&id_hotel=' . $idHotel : '');
$baseParams = array(
- 'date_from' => $dateFrom,
- 'date_to' => $dateTo,
- 'id_hotel' => $idHotel ?: false,
- 'booking_source' => $bookingSource,
+ 'date_from' => $dateFrom,
+ 'date_to' => $dateTo,
+ 'id_hotel' => $idHotel ?: false,
);
+ if ($report === 'payment-method') {
+ $filterBaseUrl .= ($paymentMethod ? '&payment_method=' . urlencode($paymentMethod) : '');
+ $baseParams['payment_method'] = $paymentMethod;
+ $this->context->smarty->assign(array(
+ 'filter_payment_method' => $paymentMethod,
+ 'payment_methods' => HotelBookingDetail::getDistinctOrderPaymentMethods($idHotel ?: false),
+ ));
+ } else {
+ $filterBaseUrl .= ($bookingSource ? '&booking_source=' . $bookingSource : '');
+ $baseParams['booking_source'] = $bookingSource;
+ }
+
$this->context->smarty->assign(array(
'filter_base_url' => $filterBaseUrl,
'filter_booking_source' => $bookingSource,
@@ -1658,6 +1669,10 @@ class QloHotelReports extends Module
'id_hotel' => $idHotel ?: false,
);
+ if ($report === 'payment-method') {
+ $baseParams['payment_method'] = pSQL(Tools::getValue('payment_method', ''));
+ }
+
if ($report === 'source') {
$rows = HotelBookingDetail::getChannelStats($baseParams);
$totalRevExcl = 0.0;
diff --git a/modules/qlohotelreports/views/templates/hook/group-channels.tpl b/modules/qlohotelreports/views/templates/hook/group-channels.tpl
index c4d973271..3b33d4f89 100644
--- a/modules/qlohotelreports/views/templates/hook/group-channels.tpl
+++ b/modules/qlohotelreports/views/templates/hook/group-channels.tpl
@@ -40,6 +40,21 @@
+ {if $active_report == 'payment-method'}
+