diff --git a/admin/themes/default/sass/controllers/_order.sass b/admin/themes/default/sass/controllers/_order.sass index fab2d5f1c..57b6189f6 100644 --- a/admin/themes/default/sass/controllers/_order.sass +++ b/admin/themes/default/sass/controllers/_order.sass @@ -27,4 +27,6 @@ max-height: 55px max-width: 55px - +.room_status_info_form + .room_status + white-space: normal \ No newline at end of file diff --git a/admin/themes/default/template/controllers/orders/_product_line.tpl b/admin/themes/default/template/controllers/orders/_product_line.tpl index a67ac7f42..a6297373a 100644 --- a/admin/themes/default/template/controllers/orders/_product_line.tpl +++ b/admin/themes/default/template/controllers/orders/_product_line.tpl @@ -23,10 +23,10 @@ * International Registered Trademark & Property of PrestaShop SA *} - + {if $refund_allowed} - + {/if} @@ -261,7 +261,7 @@
  • - {l s='Reallocate Room'} + {l s='Reallocate/Swap Room'}
  • @@ -283,4 +283,4 @@ {/if} - \ No newline at end of file + diff --git a/admin/themes/default/template/controllers/orders/helpers/view/view.tpl b/admin/themes/default/template/controllers/orders/helpers/view/view.tpl index ab5ac61dd..61db4c5f7 100644 --- a/admin/themes/default/template/controllers/orders/helpers/view/view.tpl +++ b/admin/themes/default/template/controllers/orders/helpers/view/view.tpl @@ -157,7 +157,8 @@ {/if} -->   - {if $refund_allowed && !$hasCompletelyRefunded} + + {if $refund_allowed && !$completeRefundRequestOrCancel} {if $order->getTotalPaid()|floatval} @@ -232,23 +233,26 @@ -
    -
    -
    - - -
    -
    - -
    -
    -
    + {* If current state is refunded or cancelled the further order status changes are not allowed *} + {if !isset($currentState) || (isset($currentState) && ($currentState->id != Configuration::get('PS_OS_REFUND') && $currentState->id != Configuration::get('PS_OS_CANCELED')))} +
    +
    +
    + + +
    +
    + +
    +
    +
    + {/if}
    @@ -277,61 +281,69 @@ {l s='Hotel Name'} {l s='Duration'} {l s='Documents'} - {l s='Order Status'} + {l s='Room Status'} {if isset($htl_booking_order_data) && $htl_booking_order_data} {foreach from=$htl_booking_order_data item=data} - {if !$data.is_refunded} - - - {$data['room_num']} - - - - {$data['hotel_name']} - - - - {dateFormat date=$data['date_from']} - {dateFormat date=$data['date_to']} - - - - - {l s='Documents'} {$data.num_checkin_documents} - - - -
    -
    - - - {if $data['id_status'] == $hotel_order_status['STATUS_CHECKED_IN']['id_status']} -

    {l s='Checked in on'} {dateFormat date=$data['check_in']}

    - {elseif $data['id_status'] == $hotel_order_status['STATUS_CHECKED_OUT']['id_status']} -

    {l s='Checked out on'} {dateFormat date=$data['check_out']}

    - {/if} - - {* field for the current date *} - - - - - - -
    -
    - -
    -
    - - - {/if} + + + {$data['room_num']} + + + + {$data['hotel_name']} + + + + {dateFormat date=$data['date_from']} - {dateFormat date=$data['date_to']} + + + + + {l s='Documents'} {$data.num_checkin_documents} + + + +
    +
    + {if $data.is_refunded || $data.is_cancelled} + {if $data['id_status'] == $hotel_order_status['STATUS_ALLOTED']['id_status']} +

    {l s='Room alloted'}

    + {/if} + {else} + + {/if} + + {if $data['id_status'] == $hotel_order_status['STATUS_CHECKED_IN']['id_status']} +

    {l s='Checked in on'} {dateFormat date=$data['check_in']}

    + {elseif $data['id_status'] == $hotel_order_status['STATUS_CHECKED_OUT']['id_status']} +

    {l s='Checked out on'} {dateFormat date=$data['check_out']}

    + {/if} + + {* field for the current date *} + + + + + + +
    +
    + {if $data.is_refunded || $data.is_cancelled} + {if $data.is_cancelled}{l s='Cancelled'}{else}{l s='Refunded'}{/if} + {else} + + {/if} +
    +
    + + {/foreach} {else} @@ -1187,9 +1199,11 @@ {/if} {if $can_edit} - + {if $refund_allowed && !$completeRefundRequestOrCancel} + + {/if}
    {if !$order->hasBeenDelivered()} {* - {if $refund_allowed && !$hasCompletelyRefunded} + {if $refund_allowed && !$completeRefundRequestOrCancel}
    @@ -1631,6 +1643,7 @@ {addJsDefL name='invalid_occupancy_txt'}{l s='Invalid occupancy(adults/children) found.' js=1}{/addJsDefL} {addJsDef max_child_age=$max_child_age|escape:'quotes':'UTF-8'} {addJsDef max_child_in_room=$max_child_in_room|escape:'quotes':'UTF-8'} + {addJsDefL name='undo_cancellation_success'}{l s='Booking cancellation undo process is done successfully.' js=1}{/addJsDefL} {/strip} {* Apply javascript for the page *} @@ -2119,4 +2132,4 @@ }); -{/block} \ No newline at end of file +{/block} diff --git a/classes/Cart.php b/classes/Cart.php index 9c62bc7ed..5b3711f25 100644 --- a/classes/Cart.php +++ b/classes/Cart.php @@ -2387,7 +2387,6 @@ public function getPackageList($flush = false) $array[$selectedProduct['id_hotel']] = array( 'quantity' => $selectedProduct['quantity'], 'id_hotel' => $selectedProduct['id_hotel'], - 'unit_price_tax_incl' => $selectedProduct['unit_price_tax_incl'], 'total_price_tax_excl' => $selectedProduct['total_price_tax_excl'], 'total_price_tax_incl' => $selectedProduct['total_price_tax_incl'], ); @@ -2397,7 +2396,8 @@ public function getPackageList($flush = false) $product['cart_quantity'] = $selectedProduct['quantity']; $product['total'] = $selectedProduct['total_price_tax_excl']; $product['total_wt'] = $selectedProduct['total_price_tax_incl']; - $product['price_wt'] = $selectedProduct['unit_price_tax_incl']; + $product['price_wt'] = $selectedProduct['total_price_tax_incl'] / $product['cart_quantity']; + $product['price'] = $selectedProduct['total_price_tax_excl'] / $product['cart_quantity']; $product['id_hotel'] = $selectedProduct['id_hotel']; $orderPackage[$id_address][$selectedProduct['id_hotel']]['product_list'][] = $product; if (!isset($orderPackage[$id_address][$selectedProduct['id_hotel']]['id_hotel'])) { @@ -2431,6 +2431,7 @@ public function getPackageList($flush = false) $unitPriceWt = $objHotelServiceProductCartDetail->getHotelProductUnitPrice($this->id, $product['id_product'], $hotelProduct['id_hotel'], true); $serviceProduct['total'] = $unitPrice * $hotelProduct['quantity']; $serviceProduct['total_wt'] = $unitPriceWt * $hotelProduct['quantity']; + $serviceProduct['price'] = $unitPrice; $serviceProduct['price_wt'] = $unitPriceWt; // if (!empty($hotelProducts['products'])) { // foreach($hotelProducts['products'] as $hotelProduct) { diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php index 9d2c23fb4..d162178b6 100644 --- a/classes/PaymentModule.php +++ b/classes/PaymentModule.php @@ -1008,11 +1008,9 @@ public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_ // Set the order status $new_history = new OrderHistory(); $new_history->id_order = (int)$order->id; - if ($order_status->logable && $order->is_advance_payment && $order->advance_paid_amount < $order->total_paid_tax_incl) { - $new_history->changeIdOrderState((int)Configuration::get('PS_OS_PARTIAL_PAYMENT_ACCEPTED'), $order, true); - } else { - $new_history->changeIdOrderState((int)$id_order_state, $order, true); - } + + $new_history->changeIdOrderState((int)$id_order_state, $order, true); + $new_history->addWithemail(true, $extra_vars); // Switch to back order if needed diff --git a/classes/order/Order.php b/classes/order/Order.php index a2bccc454..41b364657 100644 --- a/classes/order/Order.php +++ b/classes/order/Order.php @@ -34,6 +34,10 @@ class OrderCore extends ObjectModel const ORDER_PAYMENT_TYPE_FULL = 1; const ORDER_PAYMENT_TYPE_ADVANCE = 2; + const ORDER_COMPLETE_REFUND_FLAG = 1; + const ORDER_COMPLETE_CANCELLATION_FLAG = 2; + const ORDER_COMPLETE_CANCELLATION_OR_REFUND_REQUEST_FLAG = 3; + /** @var int Delivery address id */ public $id_address_delivery; @@ -2602,56 +2606,58 @@ public static function getAllOrdersByCartId($id_cart) return Db::getInstance()->executeS('SELECT * FROM '._DB_PREFIX_.'orders WHERE id_cart = '.(int)$id_cart); } - // Order is considered as refunded if all bookings are requested for refund and all are with refunded status - // $refundFlag [ORDER_RETURN_STATE_FLAG_REFUNDED || ORDER_RETURN_STATE_FLAG_DENIED] - public function hasCompletelyRefunded($refundFlag = 0) + /** + * Function to check if order has been completely refunded + * @param integer action: can have 3 values as below + * Order::ORDER_COMPLETE_REFUND_FLAG for complete refunded and + * Order::ORDER_COMPLETE_CANCELLATION_FLAG for completely cancelled and + * Order::ORDER_COMPLETE_CANCELLATION_OR_REFUND_REQUEST_FLAG for all rooms are either cancelled or requested for refunded + * @return boolean: true if order has been completely refunded as per requested parameters or false + */ + public function hasCompletelyRefunded($action = 0) { $objHotelBooking = new HotelBookingdetail(); - if ($refundBookings = OrderReturn::getOrdersReturnDetail($this->id)) { - if ($orderBookings = $objHotelBooking->getOrderCurrentDataByOrderId($this->id)) { - if (count($refundBookings) == count($orderBookings)) { - if ($refundFlag) { - foreach ($refundBookings as $refundRow) { - if (Validate::isLoadedObject( - $objReturnState = new OrderReturnState($refundRow['state'] - ))) { - if ($refundFlag == OrderReturnState::ORDER_RETURN_STATE_FLAG_REFUNDED - && !$objReturnState->refunded - ) { - return false; - } - if ($refundFlag == OrderReturnState::ORDER_RETURN_STATE_FLAG_DENIED - && !$objReturnState->denied - ) { - return false; - } - } + if ($orderBookings = $objHotelBooking->getOrderCurrentDataByOrderId($this->id)) { + // If action is Order::ORDER_COMPLETE_REFUND_FLAG (for refunded) then we will check + // that all rooms must be refunded and at least one booking is not cancelled + if ($action == Order::ORDER_COMPLETE_REFUND_FLAG) { + $uniqueRefundedBookings = array_unique(array_column($orderBookings, 'is_refunded')); + if (count($uniqueRefundedBookings) == 1 && $uniqueRefundedBookings[0] == 1) { + foreach ($orderBookings as $booking) { + if ($booking['is_cancelled'] == 0) { + return true; } } + } + // If action is Order::ORDER_COMPLETE_CANCELLATION_FLAG (for cancelled) then we will check that all rooms must be cancelled + } elseif ($action == Order::ORDER_COMPLETE_CANCELLATION_FLAG) { + $uniqueRefundedBookings = array_unique(array_column($orderBookings, 'is_cancelled')); + if (count($uniqueRefundedBookings) == 1 && $uniqueRefundedBookings[0] == 1) { return true; } - } - } elseif ($orderBookings = $objHotelBooking->getOrderCurrentDataByOrderId($this->id)) { - if (count(array_unique(array_column($orderBookings, 'is_cancelled'))) === 1 - && array_unique(array_column($orderBookings, 'is_cancelled'))[0] != 0 - ) { + // If action is Order::ORDER_COMPLETE_CANCELLATION_OR_REFUND_REQUEST_FLAG (for cancelled and refund requests) then we will check that all rooms are either cancelled or requested for refund + } elseif ($action == Order::ORDER_COMPLETE_CANCELLATION_OR_REFUND_REQUEST_FLAG) { + foreach ($orderBookings as $booking) { + if (!$booking['is_refunded']) { + if (!OrderReturn::getOrdersReturnDetail($this->id, 0, $booking['id'])) { + return false; + } + } + } return true; + // Default process to check if order is fully refunded or cancelled or not + } else { + // if is_refunded is 1 means booking either is cancelled or refunded. So check all bookings must have is_refunded = 1 + $uniqueRefundedBookings = array_unique(array_column($orderBookings, 'is_refunded')); + if (count($uniqueRefundedBookings) == 1 && $uniqueRefundedBookings[0] == 1) { + return true; + } } } return false; } - // Order is considered as denied if all bookings are requested for refund and all are with denied status - public function orderRefundHasBeenDenied() - { - if (OrderReturn::getOrdersReturn($this->id_customer, $this->id)) { - - } - - return false; - } - public function getWsBookings() { return Db::getInstance()->executeS( diff --git a/classes/order/OrderHistory.php b/classes/order/OrderHistory.php index 49c5db350..cc933b8bb 100644 --- a/classes/order/OrderHistory.php +++ b/classes/order/OrderHistory.php @@ -313,7 +313,6 @@ public function changeIdOrderState($new_order_state, $id_order, $use_existing_pa // set orders as paid if ($new_os->paid == 1) { - $invoices = $order->getInvoicesCollection(); if ($order->total_paid != 0) { // if order is created by API then create a direct object instead of creating an object from module if ($order->module == 'wsorder') { @@ -323,22 +322,43 @@ public function changeIdOrderState($new_order_state, $id_order, $use_existing_pa } } - foreach ($invoices as $invoice) { - /** @var OrderInvoice $invoice */ - $rest_paid = $invoice->getRestPaid(); + // if order has invoices then create payment entry for all the invoices + if ($invoices = $order->getInvoicesCollection()->getResults()) { + foreach ($invoices as $invoice) { + /** @var OrderInvoice $invoice */ + $rest_paid = $invoice->getRestPaid(); + if ($rest_paid > 0) { + if ($order->total_paid != 0) { + $payment_method = $payment_method->displayName; + } else { + $payment_method = null; + } + $order->addOrderPayment( + $rest_paid, + $payment_method, + null, + null, + null, + $invoice + ); + } + } + } else { + $rest_paid = $order->total_paid_tax_incl - $order->total_paid_real; if ($rest_paid > 0) { if ($order->total_paid != 0) { $payment_method = $payment_method->displayName; } else { $payment_method = null; } + $order->addOrderPayment( $rest_paid, $payment_method, null, null, null, - $invoice + null ); } } diff --git a/classes/order/OrderReturn.php b/classes/order/OrderReturn.php index 36614990c..a9e653da1 100644 --- a/classes/order/OrderReturn.php +++ b/classes/order/OrderReturn.php @@ -158,7 +158,8 @@ public function checkEnoughProduct($order_detail_list, $product_qty_list, $custo public function hasBeenCompleted() { if (Validate::isLoadedObject($objReturnState = new OrderReturnState($this->state))) { - if ($objReturnState->denied || $objReturnState->refunded) { + // refund process will be considered as completed when the state is "Refunded" + if ($objReturnState->refunded) { return true; } } diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index 2cfb7a044..5a23049dd 100644 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -251,7 +251,6 @@ public function __construct() $this->access_where = ' WHERE hbd.id_hotel IN ('.implode(',', $acsHtls).')'; } - parent::__construct(); } @@ -695,7 +694,79 @@ public function postProcess() $this->errors[] = Tools::displayError('The new order status is invalid.'); } else { $current_order_state = $order->getCurrentOrderState(); - if ($current_order_state->id != $order_state->id) { + + if ($current_order_state->id == Configuration::get('PS_OS_REFUND')) { + $this->errors[] = Tools::displayError('Order status can not be changed once order status is set to Refunded.'); + } elseif ($current_order_state->id == Configuration::get('PS_OS_CANCELED')) { + $this->errors[] = Tools::displayError('Order status can not be changed once order status is set to Cancelled.'); + } elseif (in_array($order_state->id, array (Configuration::get('PS_OS_OVERBOOKING_PAID'), Configuration::get('PS_OS_OVERBOOKING_UNPAID'), Configuration::get('PS_OS_OVERBOOKING_PARTIAL_PAID')))) { + $objHotelBooking = new HotelBookingDetail(); + if (!$objHotelBooking->getOverbookedRooms($order->id)) { + $this->errors[] = Tools::displayError('Order status can not be changed to any overbooking status as there are no overbooked rooms in the order.'); + } + } elseif ($order_state->id == Configuration::get('PS_OS_REFUND') + && !$order->hasCompletelyRefunded(Order::ORDER_COMPLETE_REFUND_FLAG) + ) { + $this->errors[] = Tools::displayError('Order status can not be set to Refunded until all bookings in the order are completely refunded.'); + } elseif ($order_state->id == Configuration::get('PS_OS_CANCELED') + && !$order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_FLAG) + ) { + $this->errors[] = Tools::displayError('Order status can not be set to Cancelled until all bookings in the order are cancelled.'); + } elseif ($current_order_state->id == Configuration::get('PS_OS_ERROR') && !($order_state->id == Configuration::get('PS_OS_ERROR'))) { + // All rooms must be available before changing status from Payment Error to Other status in which rooms are getting blocked again + $objHotelBooking = new HotelBookingDetail(); + if ($orderBookings = $objHotelBooking->getOrderCurrentDataByOrderId($order->id)) { + foreach ($orderBookings as $orderBooking) { + // If booking is refunded then no need to check inventory + if ((OrderReturn::getOrdersReturnDetail($order->id, 0, $orderBooking['id']) && $orderBooking['is_refunded']) + || ($orderBooking['is_cancelled'] && $orderBooking['is_refunded']) + ) { + continue; + } else { + // if inventory is available for that booking + $bookingParams = array( + 'date_from' => $orderBooking['date_from'], + 'date_to' => $orderBooking['date_to'], + 'hotel_id' => $orderBooking['id_hotel'], + 'id_room_type' => $orderBooking['id_product'], + 'only_search_data' => 1 + ); + + $objHotelBookingDetail = new HotelBookingDetail($orderBooking['id']); + if ($searchRoomsInfo = $objHotelBooking->getBookingData($bookingParams)) { + if (isset($searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available']) + && $searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available'] + ) { + $availableRoomsInfo = $searchRoomsInfo['rm_data'][$orderBooking['id_product']]['data']['available']; + if ($roomIdsAvailable = array_column($availableRoomsInfo, 'id_room')) { + // Check If room is still there in the available rooms list + if (!in_array($orderBooking['id_room'], $roomIdsAvailable)) { + $this->errors[] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.'); + + break; + } else { + $objHotelBookingDetail->is_refunded = 0; + $objHotelBookingDetail->save(); + } + } else { + $this->errors[] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.'); + break; + } + } + } else { + $this->errors[] = Tools::displayError('You can not change the order status as some rooms are not available now in this order. You can reallocate/swap rooms with other rooms to make rooms available and then change the order status.'); + + break; + } + } + } + } + } elseif ($current_order_state->id == $order_state->id) { + $this->errors[] = Tools::displayError('The order has already been assigned this status.'); + } + + // If no errors then we change the order status + if (!count($this->errors)) { // Create new OrderHistory $history = new OrderHistory(); $history->id_order = $order->id; @@ -721,11 +792,10 @@ public function postProcess() } } - Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&vieworder&token='.$this->token); + Tools::redirectAdmin(self::$currentIndex.'&id_order='.(int)$order->id.'&conf=5&vieworder&token='.$this->token); } + $this->errors[] = Tools::displayError('An error occurred while changing order status, or we were unable to send an email to the customer.'); - } else { - $this->errors[] = Tools::displayError('The order has already been assigned this status.'); } } } else { @@ -856,26 +926,58 @@ public function postProcess() } if (!count($this->errors)) { - $objOrderReturn = new OrderReturn(); - $objOrderReturn->id_customer = $order->id_customer; - $objOrderReturn->id_order = $order->id; - $objOrderReturn->state = Configuration::get('PS_ORS_PENDING'); - $objOrderReturn->by_admin = 1; - $objOrderReturn->question = $refundReason; - $objOrderReturn->save(); - if ($objOrderReturn->id) { + // if amount paid is > 0 then create refund request else cancel the booking directly + if ($order->getTotalPaid() > 0) { + $objOrderReturn = new OrderReturn(); + $objOrderReturn->id_customer = $order->id_customer; + $objOrderReturn->id_order = $order->id; + $objOrderReturn->state = Configuration::get('PS_ORS_PENDING'); + $objOrderReturn->by_admin = 1; + $objOrderReturn->question = $refundReason; + $objOrderReturn->save(); + if ($objOrderReturn->id) { + foreach ($bookings as $idHtlBooking) { + $objHtlBooking = new HotelBookingDetail($idHtlBooking); + $numDays = $objHtlBooking->getNumberOfDays( + $objHtlBooking->date_from, + $objHtlBooking->date_to + ); + $objOrderReturnDetail = new OrderReturnDetail(); + $objOrderReturnDetail->id_order_return = $objOrderReturn->id; + $objOrderReturnDetail->id_order_detail = $objHtlBooking->id_order_detail; + $objOrderReturnDetail->product_quantity = $numDays; + $objOrderReturnDetail->id_htl_booking = $idHtlBooking; + $objOrderReturnDetail->save(); + } + } + } else { + // cancel the booking directly foreach ($bookings as $idHtlBooking) { $objHtlBooking = new HotelBookingDetail($idHtlBooking); - $numDays = $objHtlBooking->getNumberOfDays( - $objHtlBooking->date_from, - $objHtlBooking->date_to - ); - $objOrderReturnDetail = new OrderReturnDetail(); - $objOrderReturnDetail->id_order_return = $objOrderReturn->id; - $objOrderReturnDetail->id_order_detail = $objHtlBooking->id_order_detail; - $objOrderReturnDetail->product_quantity = $numDays; - $objOrderReturnDetail->id_htl_booking = $idHtlBooking; - $objOrderReturnDetail->save(); + if (!$objHtlBooking->processRefundInBookingTables()) { + $this->errors[] = Tools::displayError('An error occurred while cancelling the booking.'); + } else { + // set the message for the cancellation + $message = $this->l('Room').': '.$objHtlBooking->room_num.', '.$objHtlBooking->room_type_name.' '.$this->l('has been cancelled by the hotel.'); + $message .= PHP_EOL.$this->l('Reasonn').': '.$refundReason; + $objHtlBooking->setBookingCancellationMessage($message, 1); + } + } + + // if all bookings are getting cancelled then cancel the order also + if ($order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_FLAG)) { + $objOrderHistory = new OrderHistory(); + $objOrderHistory->id_order = (int)$order->id; + + $idOrderState = Configuration::get('PS_OS_CANCELED'); + + $useExistingPayment = false; + if (!$order->hasInvoice()) { + $useExistingPayment = true; + } + + $objOrderHistory->changeIdOrderState($idOrderState, $order, $useExistingPayment); + $objOrderHistory->addWithemail(); } } } @@ -1883,13 +1985,16 @@ public function renderView() // applicable refund policies $applicableRefundPolicies = HotelOrderRefundRules::getApplicableRefundRules($order->id); + $this->tpl_view_vars = array( // refund info 'refund_allowed' => (int) $order->isReturnable(), 'applicable_refund_policies' => $applicableRefundPolicies, 'returns' => OrderReturn::getOrdersReturn($order->id_customer, $order->id), 'refundReqBookings' => $refundReqBookings, - 'hasCompletelyRefunded' => $order->hasCompletelyRefunded(), + 'completeRefundRequestOrCancel' => $order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_OR_REFUND_REQUEST_FLAG), + 'allBookingsRefunded' => $order->hasCompletelyRefunded(Order::ORDER_COMPLETE_REFUND_FLAG), + 'allBookingsCancelled' => $order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_FLAG), 'refundedAmount' => $refundedAmount, 'totalDemandsPriceTI' => $totalDemandsPriceTI, 'totalDemandsPriceTE' => $totalDemandsPriceTE, diff --git a/controllers/front/GuestTrackingController.php b/controllers/front/GuestTrackingController.php index 3cc86d316..b72bdb1c2 100644 --- a/controllers/front/GuestTrackingController.php +++ b/controllers/front/GuestTrackingController.php @@ -205,7 +205,6 @@ protected function assignOrderTracking($order_collection) $objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail(); $objRoomType = new HotelRoomType(); - $nonRequestedRooms = 0; $anyBackOrder = 0; foreach ($order_list as &$order) { @@ -570,7 +569,6 @@ protected function assignOrderTracking($order_collection) //end Hook::exec('actionOrderDetail', array('carrier' => $order->carrier, 'order' => $order)); - } } diff --git a/controllers/front/OrderConfirmationController.php b/controllers/front/OrderConfirmationController.php index 40955333f..158c239b2 100644 --- a/controllers/front/OrderConfirmationController.php +++ b/controllers/front/OrderConfirmationController.php @@ -110,7 +110,6 @@ public function initContent() /*By webkul to show order details properly on order history page*/ if (Module::isInstalled('hotelreservationsystem')) { require_once _PS_MODULE_DIR_.'hotelreservationsystem/define.php'; - $non_requested_rooms = 0; $any_back_order = 0; $processed_product = array(); $orderTotalInfo = array(); @@ -186,12 +185,6 @@ public function initContent() /*Product price when order was created*/ $order_details_obj = new OrderDetail($data_v['id_order_detail']); $cart_htl_data[$type_key]['name'] = $order_details_obj->product_name; - // $ord_refnd_info = $obj_ord_ref_info->getOderRefundInfoByIdOrderIdProductByDate($this->id_order, $type_value['product_id'], $data_v['date_from'], $data_v['date_to']); - // if ($ord_refnd_info) { - // $stage_name = $obj_refund_stages->getNameById($ord_refnd_info['refund_stage_id']); - // } else { - // $non_requested_rooms = 1; - // } $stage_name = ''; if (isset($cart_htl_data[$type_key]['date_diff'][$date_join])) { $cart_htl_data[$type_key]['date_diff'][$date_join]['num_rm'] += 1; @@ -403,7 +396,6 @@ public function initContent() } $this->context->smarty->assign('orderTotalInfo', $orderTotalInfo); - $this->context->smarty->assign('non_requested_rooms', $non_requested_rooms); $this->context->smarty->assign('orders_has_invoice', $orders_has_invoice); } diff --git a/controllers/front/OrderDetailController.php b/controllers/front/OrderDetailController.php index 196091216..e5b3260e1 100644 --- a/controllers/front/OrderDetailController.php +++ b/controllers/front/OrderDetailController.php @@ -244,41 +244,70 @@ public function initContent() } $res = true; if (!$hasError) { - if ((int)$order->total_paid_real == 0){ + $hasCancelled = 0; + // if amount paid is > 0 then create refund request else cancel the booking directly + if ($order->getTotalPaid() > 0) { + $objOrderReturn = new OrderReturn(); + $objOrderReturn->id_customer = $order->id_customer; + $objOrderReturn->id_order = $order->id; + $objOrderReturn->state = 0; + $objOrderReturn->by_admin = 0; + $objOrderReturn->question = $refundReason; + $objOrderReturn->save(); + if ($objOrderReturn->id) { + foreach ($bookingRefunds as $idHtlBooking) { + $objHtlBooking = new HotelBookingDetail($idHtlBooking); + $numDays = $objHtlBooking->getNumberOfDays( + $objHtlBooking->date_from, + $objHtlBooking->date_to + ); + + $objOrderReturnDetail = new OrderReturnDetail(); + $objOrderReturnDetail->id_order_return = $objOrderReturn->id; + $objOrderReturnDetail->id_order_detail = $objHtlBooking->id_order_detail; + $objOrderReturnDetail->product_quantity = $numDays; + $objOrderReturnDetail->id_htl_booking = $idHtlBooking; + $objOrderReturnDetail->save(); + } + } + // Emails to customer, admin on refund request state change + $objOrderReturn->changeIdOrderReturnState(Configuration::get('PS_ORS_PENDING')); + } else { + $hasCancelled = 1; + // cancel the booking directly foreach ($bookingRefunds as $idHtlBooking) { $objHtlBooking = new HotelBookingDetail($idHtlBooking); - $objHtlBooking->save(); + if (!$objHtlBooking->processRefundInBookingTables()) { + die(json_encode(array('status' => 0))); + } else { + // set the message for the cancellation + $message = Tools::displayError('1 Room from').' '.', '.$objHtlBooking->room_type_name.' '.Tools::displayError('has been cancelled by the hotel.'); + $message .= PHP_EOL.Tools::displayError('Reason').': '.$refundReason; + + $objHtlBooking->setBookingCancellationMessage($refundReason); + } } - } - $objOrderReturn = new OrderReturn(); - $objOrderReturn->id_customer = $order->id_customer; - $objOrderReturn->id_order = $order->id; - $objOrderReturn->state = 0; - $objOrderReturn->by_admin = 0; - $objOrderReturn->question = $refundReason; - $objOrderReturn->save(); - if ($objOrderReturn->id) { - foreach ($bookingRefunds as $idHtlBooking) { - $objHtlBooking = new HotelBookingDetail($idHtlBooking); - $numDays = $objHtlBooking->getNumberOfDays( - $objHtlBooking->date_from, - $objHtlBooking->date_to - ); - - $objOrderReturnDetail = new OrderReturnDetail(); - $objOrderReturnDetail->id_order_return = $objOrderReturn->id; - $objOrderReturnDetail->id_order_detail = $objHtlBooking->id_order_detail; - $objOrderReturnDetail->product_quantity = $numDays; - $objOrderReturnDetail->id_htl_booking = $idHtlBooking; - $objOrderReturnDetail->save(); + // if all bookings are getting cancelled then cancel the order also + if ($order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_FLAG)) { + $objOrderHistory = new OrderHistory(); + $objOrderHistory->id_order = (int)$order->id; + + $idOrderState = Configuration::get('PS_OS_CANCELED'); + + $useExistingPayment = false; + if (!$order->hasInvoice()) { + $useExistingPayment = true; + } + + $objOrderHistory->changeIdOrderState($idOrderState, $order, $useExistingPayment); + $objOrderHistory->addWithemail(); } } - // Emails to customer, admin on refund request state change - $objOrderReturn->changeIdOrderReturnState(Configuration::get('PS_ORS_PENDING')); - die(json_encode(array('status' => 1))); + die(json_encode(array('status' => 1, 'has_cancelled' => $hasCancelled))); } + die(json_encode(array('status' => 0))); } } else { @@ -322,7 +351,6 @@ public function initContent() $objRoomType = new HotelRoomType(); $objBookingDemand = new HotelBookingDemands(); $objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail(); - $nonRequestedRooms = 1; $anyBackOrder = 0; $processedProducts = array(); $cartHotelData = array(); @@ -618,7 +646,6 @@ public function initContent() 'order_has_invoice' => $order->hasInvoice(), 'cart_htl_data' => $cartHotelData, 'cart_service_products' => $cartServiceProducts, - 'non_requested_rooms' => $nonRequestedRooms, ) ); // } @@ -635,7 +662,7 @@ public function initContent() 'refund_allowed' => (int) $order->isReturnable(), 'returns' => OrderReturn::getOrdersReturn($order->id_customer, $order->id), 'refundReqBookings' => $refundReqBookings, - 'hasCompletelyRefunded' => $order->hasCompletelyRefunded(), + 'completeRefundRequestOrCancel' => $order->hasCompletelyRefunded(Order::ORDER_COMPLETE_CANCELLATION_OR_REFUND_REQUEST_FLAG), 'refundedAmount' => $refundedAmount, 'shop_name' => strval(Configuration::get('PS_SHOP_NAME')), 'order' => $order, @@ -693,4 +720,4 @@ public function setMedia() $this->addCSS(_THEME_CSS_DIR_.'addresses.css'); } } -} \ No newline at end of file +} diff --git a/install/langs/bg/data/order_state.xml b/install/langs/bg/data/order_state.xml index f22b1f4be..c1d4db4c4 100644 --- a/install/langs/bg/data/order_state.xml +++ b/install/langs/bg/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Получено пълно плащане diff --git a/install/langs/bn/data/order_state.xml b/install/langs/bn/data/order_state.xml index e966ff68a..f727c14a3 100644 --- a/install/langs/bn/data/order_state.xml +++ b/install/langs/bn/data/order_state.xml @@ -5,7 +5,7 @@ - পেমেন্ট গৃহীত + সম্পূর্ণ পেমেন্ট প্রাপ্ত diff --git a/install/langs/br/data/order_state.xml b/install/langs/br/data/order_state.xml index 62d5f9206..7cb239191 100644 --- a/install/langs/br/data/order_state.xml +++ b/install/langs/br/data/order_state.xml @@ -5,7 +5,7 @@ - Pagamento aceito + Pagamento completo recebido diff --git a/install/langs/cs/data/order_state.xml b/install/langs/cs/data/order_state.xml index f14803ab3..c349433f1 100644 --- a/install/langs/cs/data/order_state.xml +++ b/install/langs/cs/data/order_state.xml @@ -5,7 +5,7 @@ - Platba byla přijata + Byla přijata úplná platba diff --git a/install/langs/de/data/order_state.xml b/install/langs/de/data/order_state.xml index 2ac2ea90b..921cb4aab 100644 --- a/install/langs/de/data/order_state.xml +++ b/install/langs/de/data/order_state.xml @@ -5,7 +5,7 @@ - Zahlung eingegangen + Vollständige Zahlung erhalten diff --git a/install/langs/en/data/order_state.xml b/install/langs/en/data/order_state.xml index f22b1f4be..b4714fb54 100644 --- a/install/langs/en/data/order_state.xml +++ b/install/langs/en/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Complete payment received diff --git a/install/langs/es/data/order_state.xml b/install/langs/es/data/order_state.xml index 4f4b7059b..91c9ef4b1 100644 --- a/install/langs/es/data/order_state.xml +++ b/install/langs/es/data/order_state.xml @@ -5,7 +5,7 @@ - Pago aceptado + Pago completo recibido diff --git a/install/langs/fa/data/order_state.xml b/install/langs/fa/data/order_state.xml index 75a6f109d..a0a599e41 100644 --- a/install/langs/fa/data/order_state.xml +++ b/install/langs/fa/data/order_state.xml @@ -5,7 +5,7 @@ - پرداخت تایید شده + پرداخت کامل دریافت شد diff --git a/install/langs/fr/data/order_state.xml b/install/langs/fr/data/order_state.xml index 55e21df4f..736388cc3 100644 --- a/install/langs/fr/data/order_state.xml +++ b/install/langs/fr/data/order_state.xml @@ -5,7 +5,7 @@ - Paiement accepté + Paiement complet reçu diff --git a/install/langs/he/data/order_state.xml b/install/langs/he/data/order_state.xml index 1907a4f6b..9cb60de92 100644 --- a/install/langs/he/data/order_state.xml +++ b/install/langs/he/data/order_state.xml @@ -5,7 +5,7 @@ - התקבל תשלום + תשלום מלא התקבל diff --git a/install/langs/hr/data/order_state.xml b/install/langs/hr/data/order_state.xml index f22b1f4be..d5e3c32c4 100644 --- a/install/langs/hr/data/order_state.xml +++ b/install/langs/hr/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Potpuna uplata primljena diff --git a/install/langs/hu/data/order_state.xml b/install/langs/hu/data/order_state.xml index f22b1f4be..bf97e806c 100644 --- a/install/langs/hu/data/order_state.xml +++ b/install/langs/hu/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Teljes fizetés megérkezett diff --git a/install/langs/id/data/order_state.xml b/install/langs/id/data/order_state.xml index 16815db43..3b87e26b2 100644 --- a/install/langs/id/data/order_state.xml +++ b/install/langs/id/data/order_state.xml @@ -5,7 +5,7 @@ - Pembayaran diterima + Pembayaran lengkap diterima diff --git a/install/langs/it/data/order_state.xml b/install/langs/it/data/order_state.xml index 9df4e2ac4..d80b7467d 100644 --- a/install/langs/it/data/order_state.xml +++ b/install/langs/it/data/order_state.xml @@ -5,7 +5,7 @@ - Pagamento accettato + Pagamento completo ricevuto diff --git a/install/langs/lt/data/order_state.xml b/install/langs/lt/data/order_state.xml index f22b1f4be..e108d40ce 100644 --- a/install/langs/lt/data/order_state.xml +++ b/install/langs/lt/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Gautas pilnas mokėjimas diff --git a/install/langs/mk/data/order_state.xml b/install/langs/mk/data/order_state.xml index f22b1f4be..6f3789e59 100644 --- a/install/langs/mk/data/order_state.xml +++ b/install/langs/mk/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Добиена е целосна исплата diff --git a/install/langs/nl/data/order_state.xml b/install/langs/nl/data/order_state.xml index 0b5e4683b..b34506d95 100644 --- a/install/langs/nl/data/order_state.xml +++ b/install/langs/nl/data/order_state.xml @@ -5,7 +5,7 @@ - Betaling aanvaard + Volledige betaling ontvangen diff --git a/install/langs/no/data/order_state.xml b/install/langs/no/data/order_state.xml index f22b1f4be..b4714fb54 100644 --- a/install/langs/no/data/order_state.xml +++ b/install/langs/no/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Complete payment received diff --git a/install/langs/pl/data/order_state.xml b/install/langs/pl/data/order_state.xml index f216ff27c..08c49eb92 100644 --- a/install/langs/pl/data/order_state.xml +++ b/install/langs/pl/data/order_state.xml @@ -5,7 +5,7 @@ - Płatność zaakceptowana + Otrzymano pełną płatność diff --git a/install/langs/pt/data/order_state.xml b/install/langs/pt/data/order_state.xml index 709c8ce76..7c2bce22e 100644 --- a/install/langs/pt/data/order_state.xml +++ b/install/langs/pt/data/order_state.xml @@ -5,7 +5,7 @@ - Pagamento aceite + Pagamento completo recebido diff --git a/install/langs/qc/data/order_state.xml b/install/langs/qc/data/order_state.xml index 3d7c8b67b..d499bf3b5 100644 --- a/install/langs/qc/data/order_state.xml +++ b/install/langs/qc/data/order_state.xml @@ -5,7 +5,7 @@ - Paiement accepté + Paiement complet reçu diff --git a/install/langs/ro/data/order_state.xml b/install/langs/ro/data/order_state.xml index 14f13d0e3..11ca25a0b 100644 --- a/install/langs/ro/data/order_state.xml +++ b/install/langs/ro/data/order_state.xml @@ -5,7 +5,7 @@ - Plată acceptată + Plata completă primită diff --git a/install/langs/ru/data/order_state.xml b/install/langs/ru/data/order_state.xml index c2bcb5ccc..fb864990e 100644 --- a/install/langs/ru/data/order_state.xml +++ b/install/langs/ru/data/order_state.xml @@ -5,7 +5,7 @@ - Платеж принят + Полная оплата получена diff --git a/install/langs/si/data/order_state.xml b/install/langs/si/data/order_state.xml index f22b1f4be..7d88f9612 100644 --- a/install/langs/si/data/order_state.xml +++ b/install/langs/si/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + සම්පූර්ණ ගෙවීමක් ලැබිණි diff --git a/install/langs/sr/data/order_state.xml b/install/langs/sr/data/order_state.xml index f22b1f4be..753d2f254 100644 --- a/install/langs/sr/data/order_state.xml +++ b/install/langs/sr/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Примљена комплетна уплата diff --git a/install/langs/sv/data/order_state.xml b/install/langs/sv/data/order_state.xml index f22b1f4be..bad3427b1 100644 --- a/install/langs/sv/data/order_state.xml +++ b/install/langs/sv/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + Fullständig betalning mottagen diff --git a/install/langs/tw/data/order_state.xml b/install/langs/tw/data/order_state.xml index 05008b4f9..36c90c477 100644 --- a/install/langs/tw/data/order_state.xml +++ b/install/langs/tw/data/order_state.xml @@ -5,7 +5,7 @@ - 付款完成 + 已收到完整付款 diff --git a/install/langs/vn/data/order_state.xml b/install/langs/vn/data/order_state.xml index f2d195131..91a6c0096 100644 --- a/install/langs/vn/data/order_state.xml +++ b/install/langs/vn/data/order_state.xml @@ -5,7 +5,7 @@ - Thanh toán được chấp nhận + Đã nhận được thanh toán đầy đủ diff --git a/install/langs/zh/data/order_state.xml b/install/langs/zh/data/order_state.xml index f22b1f4be..68f8b1f1f 100644 --- a/install/langs/zh/data/order_state.xml +++ b/install/langs/zh/data/order_state.xml @@ -5,7 +5,7 @@ - Payment accepted + 已收到完整付款 diff --git a/modules/hotelreservationsystem/classes/HotelBookingDetail.php b/modules/hotelreservationsystem/classes/HotelBookingDetail.php index b52743635..50b765386 100644 --- a/modules/hotelreservationsystem/classes/HotelBookingDetail.php +++ b/modules/hotelreservationsystem/classes/HotelBookingDetail.php @@ -2709,4 +2709,185 @@ public function getOrderStatusToFreeBookedRoom() Configuration::get('PS_OS_ERROR'), )); } -} \ No newline at end of file + + // process the booking tables changes when a booking refund/cancellation is processed + public function processRefundInBookingTables() + { + if (Validate::isLoadedObject($this)) { + $reduction_amount = array( + 'total_price_tax_excl' => 0, + 'total_price_tax_incl' => 0, + 'total_products_tax_excl' => 0, + 'total_products_tax_incl' => 0, + ); + $objOrder = new Order($this->id_order); + $orderTotalPaid = $objOrder->getTotalPaid(); + + // things to do if order is not paid + if ((float) $orderTotalPaid <= 0) { + $objHotelBookingDemands = new HotelBookingDemands(); + $objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail(); + + $reduction_amount['total_price_tax_excl'] = Tools::ps_round((float) $this->total_price_tax_excl, 6); + $reduction_amount['total_products_tax_excl'] = Tools::ps_round((float) $this->total_price_tax_excl, 6); + $reduction_amount['total_price_tax_incl'] = Tools::ps_round((float) $this->total_price_tax_incl, 6); + $reduction_amount['total_products_tax_incl'] = Tools::ps_round((float) $this->total_price_tax_incl, 6); + + // reduce facilities amount from order and services_detail + if ($roomDemands = $objHotelBookingDemands->getRoomTypeBookingExtraDemands( + $this->id_order, + $this->id_product, + $this->id_room, + $this->date_from, + $this->date_to, + 0 + )) { + foreach ($roomDemands as $roomDemand) { + $objHotelBookingDemands = new HotelBookingDemands($roomDemand['id_booking_demand']); + $reduction_amount['total_price_tax_excl'] += Tools::ps_round((float) $objHotelBookingDemands->total_price_tax_excl, 6); + $reduction_amount['total_price_tax_incl'] += Tools::ps_round((float) $objHotelBookingDemands->total_price_tax_incl, 6); + $objHotelBookingDemands->total_price_tax_excl = 0; + $objHotelBookingDemands->total_price_tax_incl = 0; + $objHotelBookingDemands->save(); + } + } + + // reduce services amount from order and services_detail + if ($roomServices = $objRoomTypeServiceProductOrderDetail->getSelectedServicesForRoom( + $this->id + )) { + foreach ($roomServices['additional_services'] as $roomService) { + $objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail( + $roomService['id_room_type_service_product_order_detail'] + ); + $reduction_amount['total_price_tax_excl'] += Tools::ps_round((float) $objRoomTypeServiceProductOrderDetail->total_price_tax_excl, 6); + $reduction_amount['total_products_tax_excl'] += Tools::ps_round((float) $objRoomTypeServiceProductOrderDetail->total_price_tax_excl, 6); + $reduction_amount['total_price_tax_incl'] += Tools::ps_round((float) $objRoomTypeServiceProductOrderDetail->total_price_tax_incl, 6); + $reduction_amount['total_products_tax_incl'] += Tools::ps_round((float) $objRoomTypeServiceProductOrderDetail->total_price_tax_incl, 6); + + if (Validate::isLoadedObject($objOrderDetail = new OrderDetail($objRoomTypeServiceProductOrderDetail->id_order_detail))) { + $objOrderDetail->product_quantity_refunded += $objRoomTypeServiceProductOrderDetail->quantity; + if ($objOrderDetail->product_quantity_refunded > $objOrderDetail->product_quantity) { + $objOrderDetail->product_quantity_refunded = $objOrderDetail->product_quantity; + } + + $objOrderDetail->total_price_tax_excl -= Tools::ps_round((float) $objRoomTypeServiceProductOrderDetail->total_price_tax_excl, 6); + $objOrderDetail->total_price_tax_incl -= Tools::ps_round((float) $objRoomTypeServiceProductOrderDetail->total_price_tax_incl, 6); + + $objOrderDetail->save(); + } + + $objRoomTypeServiceProductOrderDetail->total_price_tax_excl = 0; + $objRoomTypeServiceProductOrderDetail->total_price_tax_incl = 0; + $objRoomTypeServiceProductOrderDetail->save(); + } + } + } + + // enter refunded quantity in the order detail table + $idOrderDetail = $this->id_order_detail; + if (Validate::isLoadedObject($objOrderDetail = new OrderDetail($idOrderDetail))) { + $numDays = $this->getNumberOfDays( + $this->date_from, + $this->date_to + ); + + $objOrderDetail->product_quantity_refunded += $numDays; + if ($objOrderDetail->product_quantity_refunded > $objOrderDetail->product_quantity) { + $objOrderDetail->product_quantity_refunded = $objOrderDetail->product_quantity; + } + + if ((float) $orderTotalPaid <= 0) { + // reduce room amount from order and order detail + $objOrderDetail->total_price_tax_incl -= Tools::ps_round((float) $this->total_price_tax_incl, 6); + $objOrderDetail->total_price_tax_excl -= Tools::ps_round((float) $this->total_price_tax_excl, 6); + if (Validate::isLoadedObject($objOrder = new Order($this->id_order))) { + $objOrder->total_paid -= $reduction_amount['total_price_tax_incl']; + $objOrder->total_paid_tax_excl -= Tools::ps_round((float) $reduction_amount['total_price_tax_excl'], 6); + $objOrder->total_paid_tax_incl -= Tools::ps_round((float) $reduction_amount['total_price_tax_incl'], 6); + $objOrder->total_products -= Tools::ps_round((float) $reduction_amount['total_products_tax_excl'], 6); + $objOrder->total_products_wt -= Tools::ps_round((float) $reduction_amount['total_products_tax_incl'], 6); + $objOrder->save(); + } + } + + $objOrderDetail->save(); + } + + // as refund is completed then set the booking as refunded + $this->is_refunded = 1; + if ((float) $orderTotalPaid <= 0) { + // Reduce room amount from htl_booking_detail + $this->is_cancelled = 1; + $this->total_price_tax_excl = 0; + $this->total_price_tax_incl = 0; + } + + $this->save(); + + return true; + } + + return false; + } + + public function setBookingCancellationMessage($message, $byAdmin = 0) + { + if (Validate::isLoadedObject($this)) { + // First save the message for the admin for the refund + $objectMessage = new Message(); + $objectMessage->message = $message; + $objectMessage->id_cart = (int)$this->id_cart; + $objectMessage->id_customer = (int)($this->id_customer); + $objectMessage->id_order = (int)$this->id_order; + $objectMessage->private = 1; + + // If cancelled by admin then set the employee id who is doing this cancellation else put 0 + $context = Context::getContext(); + if ($byAdmin) { + $objectMessage->id_employee = (int)$context->employee->id; + } else { + $objectMessage->id_employee = 0; + } + + $objectMessage->add(); + + // save this message for the customer + $objCustomer = new Customer($this->id_customer); + $idCustomerThread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($objCustomer->email, $this->id_order); + if (!$idCustomerThread) { + $objCustomerThread = new CustomerThread(); + $objCustomerThread->id_contact = 0; + $objCustomerThread->id_customer = (int)$this->id_customer; + $objCustomerThread->id_shop = (int)$context->shop->id; + $objCustomerThread->id_order = (int)$this->id_order; + $objCustomerThread->id_lang = (int)$context->language->id; + $objCustomerThread->email = $objCustomer->email; + $objCustomerThread->status = 'open'; + $objCustomerThread->token = Tools::passwdGen(12); + $objCustomerThread->add(); + } else { + $objCustomerThread = new CustomerThread((int)$idCustomerThread); + } + + $objCustomerMessage = new CustomerMessage(); + $objCustomerMessage->id_customer_thread = $objCustomerThread->id; + + // If cancelled by admin then set the employee id who is doing this cancellation else put 0 + if ($byAdmin) { + $objCustomerMessage->id_employee = (int)$context->employee->id; + } else { + $objCustomerMessage->id_employee = 0; + } + + $objCustomerMessage->message = $message; + $objCustomerMessage->private = 0; + + $objCustomerMessage->add(); + + return true; + } + + return false; + } +} diff --git a/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php b/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php index 6b917f75b..75671e8b9 100644 --- a/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php +++ b/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php @@ -292,27 +292,46 @@ public function postProcess() } else { $this->errors[] = $this->l('Invalid refund amount(s) entered.'); } - } else { - $this->errors[] = $this->l('Select at least one booking for refund.'); - } - if (Tools::isSubmit('refundTransactionAmount')) { - $paymentMode = Tools::getValue('payment_method'); - if (!$paymentMode) { - $paymentMode = Tools::getValue('other_payment_mode'); - if (!$paymentMode) { - $this->errors[] = $this->l('Please enter the payment mode of the refund transaction.'); - } elseif (!Validate::isGenericName($paymentMode)) { - $this->errors[] = $this->l('Invalid payment mode entered.'); + // If there are no errors in the refund amounts the check validations depends on refund amount + if (!count($this->errors)) { + $totalRefundAmount = array_sum($refundedAmounts); + if (Tools::isSubmit('generateCreditSlip')) { + if ($totalRefundAmount <= 0) { + $this->errors[] = $this->l('Invalid refund amount(s) for generating credit slip.'); + } } - } + if (Tools::isSubmit('generateDiscount')) { + if ($totalRefundAmount <= 0) { + $this->errors[] = $this->l('Invalid refund amount(s) for generating voucher.'); + } + } + + if (Tools::isSubmit('refundTransactionAmount')) { + if ($totalRefundAmount <= 0) { + $this->errors[] = $this->l('Invalid refund amount(s) for entering refund transaction details.'); + } else { + $paymentMode = Tools::getValue('payment_method'); + if (!$paymentMode) { + $paymentMode = Tools::getValue('other_payment_mode'); + if (!$paymentMode) { + $this->errors[] = $this->l('Please enter the payment mode of the refund transaction.'); + } elseif (!Validate::isGenericName($paymentMode)) { + $this->errors[] = $this->l('Invalid payment mode entered.'); + } + } - $idTransaction = Tools::getValue('id_transaction'); - if (!$idTransaction) { - $this->errors[] = $this->l('Please enter the transaction id of the refund transaction.'); - } elseif (!Validate::isGenericName($idTransaction)) { - $this->errors[] = $this->l('Invalid transaction id entered.'); + $idTransaction = Tools::getValue('id_transaction'); + if (!$idTransaction) { + $this->errors[] = $this->l('Please enter the transaction id of the refund transaction.'); + } elseif (!Validate::isGenericName($idTransaction)) { + $this->errors[] = $this->l('Invalid transaction id entered.'); + } + } + } } + } else { + $this->errors[] = $this->l('Select at least one booking for refund.'); } } } @@ -320,149 +339,60 @@ public function postProcess() $this->errors[] = $this->l('Invalid refund state.'); } } else { - $this->errors[] = $this->l('Invalid refund info.'); + $this->errors[] = $this->l('Invalid refund information found.'); } if (!count($this->errors)) { $bookingList = array(); $totalRefundedAmount = 0; - if ($objRefundState->refunded || $objRefundState->denied) { - $objHotelBookingDemands = new HotelBookingDemands(); - $objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail(); + // If refund is completed then work on the booking list + if ($objRefundState->refunded) { foreach ($idsReturnDetail as $idRetDetail) { $objOrderReturnDetail = new OrderReturnDetail($idRetDetail); - // set booking as refunded if return state is refunded/denied $idHtlBooking = $objOrderReturnDetail->id_htl_booking; - $numDays = 1; - $idOrderDetail = 0; $reduction_amount = array( 'total_price_tax_excl' => 0, 'total_price_tax_incl' => 0, 'total_products_tax_excl' => 0, 'total_products_tax_incl' => 0, ); - if (Validate::isLoadedObject($objHtlBooking = new HotelBookingDetail($idHtlBooking))) { - $objHtlBooking->is_refunded = 1; - $numDays = $objHtlBooking->getNumberOfDays( - $objHtlBooking->date_from, - $objHtlBooking->date_to - ); - - if ((float) $orderTotalPaid <= 0) { - $reduction_amount['total_price_tax_excl'] = $objHtlBooking->total_price_tax_excl; - $reduction_amount['total_products_tax_excl'] = $objHtlBooking->total_price_tax_excl; - $reduction_amount['total_price_tax_incl'] = $objHtlBooking->total_price_tax_incl; - $reduction_amount['total_products_tax_incl'] = $objHtlBooking->total_price_tax_incl; - // reduce facilities amount from order and services_detail - if ($roomDemands = $objHotelBookingDemands->getRoomTypeBookingExtraDemands( - $objHtlBooking->id_order, - $objHtlBooking->id_product, - $objHtlBooking->id_room, - $objHtlBooking->date_from, - $objHtlBooking->date_to, - 0 - )) { - foreach ($roomDemands as $roomDemand) { - $objHotelBookingDemands = new HotelBookingDemands($roomDemand['id_booking_demand']); - $reduction_amount['total_price_tax_excl'] += $objHotelBookingDemands->total_price_tax_excl; - $reduction_amount['total_price_tax_incl'] += $objHotelBookingDemands->total_price_tax_incl; - $objHotelBookingDemands->total_price_tax_excl = 0; - $objHotelBookingDemands->total_price_tax_incl = 0; - $objHotelBookingDemands->save(); - } - } - // reduce services amount from order and services_detail - if ($roomServices = $objRoomTypeServiceProductOrderDetail->getSelectedServicesForRoom( - $objHtlBooking->id - )) { - foreach ($roomServices['additional_services'] as $roomService) { - $objRoomTypeServiceProductOrderDetail = new RoomTypeServiceProductOrderDetail( - $roomService['id_room_type_service_product_order_detail'] - ); - $reduction_amount['total_price_tax_excl'] += $objRoomTypeServiceProductOrderDetail->total_price_tax_excl; - $reduction_amount['total_products_tax_excl'] += $objRoomTypeServiceProductOrderDetail->total_price_tax_excl; - $reduction_amount['total_price_tax_incl'] += $objRoomTypeServiceProductOrderDetail->total_price_tax_incl; - $reduction_amount['total_products_tax_incl'] += $objRoomTypeServiceProductOrderDetail->total_price_tax_incl; - - if (Validate::isLoadedObject($objOrderDetail = new OrderDetail($objRoomTypeServiceProductOrderDetail->id_order_detail))) { - $objOrderDetail->product_quantity_refunded += $objRoomTypeServiceProductOrderDetail->quantity; - if ($objOrderDetail->product_quantity_refunded > $objOrderDetail->product_quantity) { - $objOrderDetail->product_quantity_refunded = $objOrderDetail->product_quantity; - } + $objHtlBooking = new HotelBookingDetail($idHtlBooking); + // perform booking refund processes in the booking tables + $objHtlBooking->processRefundInBookingTables(); - $objOrderDetail->total_price_tax_excl -= $objRoomTypeServiceProductOrderDetail->total_price_tax_excl; - $objOrderDetail->total_price_tax_incl -= $objRoomTypeServiceProductOrderDetail->total_price_tax_incl; - $objOrderDetail->save(); - } + // save individual booking amount for every booking refund + $refundedAmount = $refundedAmounts[$idRetDetail]; + $objOrderReturnDetail->refunded_amount = $refundedAmount; + $objOrderReturnDetail->save(); - $objRoomTypeServiceProductOrderDetail->total_price_tax_excl = 0; - $objRoomTypeServiceProductOrderDetail->total_price_tax_incl = 0; - $objRoomTypeServiceProductOrderDetail->save(); - } - } + // sum the refund amount for total order refund amount + $totalRefundedAmount += $refundedAmount; - } + if (Tools::isSubmit('generateCreditSlip')) { + $numDays = $objHtlBooking->getNumberOfDays( + $objHtlBooking->date_from, + $objHtlBooking->date_to + ); - // enter refunded quantity in the order detail table + $objHtlBooking = new HotelBookingDetail($idHtlBooking); $idOrderDetail = $objHtlBooking->id_order_detail; - if (Validate::isLoadedObject($objOrderDetail = new OrderDetail($idOrderDetail))) { - $objOrderDetail->product_quantity_refunded += $numDays; - if ($objOrderDetail->product_quantity_refunded > $objOrderDetail->product_quantity) { - $objOrderDetail->product_quantity_refunded = $objOrderDetail->product_quantity; - } - - if ((float) $orderTotalPaid <= 0) { - // reduce room amount from order and order detail - $objOrderDetail->total_price_tax_incl -= $objHtlBooking->total_price_tax_incl; - $objOrderDetail->total_price_tax_excl -= $objHtlBooking->total_price_tax_excl; - if (Validate::isLoadedObject($objOrder = new Order($objHtlBooking->id_order))) { - $objOrder->total_paid -= $reduction_amount['total_price_tax_incl']; - $objOrder->total_paid_tax_excl -= $reduction_amount['total_price_tax_excl']; - $objOrder->total_paid_tax_incl -= $reduction_amount['total_price_tax_incl']; - $objOrder->total_products -= $reduction_amount['total_products_tax_excl']; - $objOrder->total_products_wt -= $reduction_amount['total_products_tax_incl']; - $objOrder->save(); - } - } - $objOrderDetail->save(); - } - if ((float) $orderTotalPaid <= 0) { - // reduce room amount from htl_booking_detail - $objHtlBooking->is_cancelled = 1; - $objHtlBooking->total_price_tax_excl = 0; - $objHtlBooking->total_price_tax_incl = 0; - } - $objHtlBooking->save(); - } - // save individual booking amount for every booking refund - if ($objRefundState->refunded) { - $refundedAmount = $refundedAmounts[$idRetDetail]; - $objOrderReturnDetail->refunded_amount = $refundedAmount; - $objOrderReturnDetail->save(); - - // sum the refund amount for total order refund amount - $totalRefundedAmount += $refundedAmount; - - if (Tools::isSubmit('generateCreditSlip')) { - $bookingList[$idHtlBooking] = array( - 'id_htl_booking' => $idHtlBooking, - 'id_order_detail' => $idOrderDetail, - 'quantity' => $numDays, - 'num_days' => $numDays, - 'unit_price' => $refundedAmount / $numDays, - 'amount' => $refundedAmount, - ); - } + $bookingList[$idHtlBooking] = array( + 'id_htl_booking' => $idHtlBooking, + 'id_order_detail' => $idOrderDetail, + 'quantity' => $numDays, + 'num_days' => $numDays, + 'unit_price' => $refundedAmount / $numDays, + 'amount' => $refundedAmount, + ); } - } // if bookings are refunded then set the payment information - if ($objRefundState->refunded && (float) $orderTotalPaid > 0) { + if ((float) $orderTotalPaid > 0) { if (Tools::isSubmit('refundTransactionAmount')) { $objOrderReturn->payment_mode = $paymentMode; $objOrderReturn->id_transaction = $idTransaction; @@ -480,18 +410,20 @@ public function postProcess() // change state of the order refund $objOrderReturn->changeIdOrderReturnState($idRefundState); + // change state of the order to refunded if all the room bookings in the order are completely refunded if ($objRefundState->refunded) { - // check if order is paid the set status of the order to refunded - $objOrderHistory = new OrderHistory(); - $objOrderHistory->id_order = (int)$objOrder->id; - - if ($objOrder->hasCompletelyRefunded(OrderReturnState::ORDER_RETURN_STATE_FLAG_REFUNDED)) { - $idOrderState = null; - if ((float) $orderTotalPaid) { - $idOrderState = Configuration::get('PS_OS_REFUND'); - } else { - $idOrderState = Configuration::get('PS_OS_CANCELED'); - } + $idOrderState = 0; + if ($objOrder->hasCompletelyRefunded(Order::ORDER_COMPLETE_REFUND_FLAG)) { + $idOrderState = Configuration::get('PS_OS_REFUND'); + } elseif ($objOrder->hasCompletelyRefunded(Order::ORDER_COMPLETE_REFUND_FLAG)) { + $idOrderState = Configuration::get('PS_OS_CANCELED'); + } + + // If order is completely refunded or cancelled then change the order state + if ($idOrderState) { + // check if order is paid the set status of the order to refunded + $objOrderHistory = new OrderHistory(); + $objOrderHistory->id_order = (int)$objOrder->id; $useExistingPayment = false; if (!$objOrder->hasInvoice()) { diff --git a/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js b/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js index 8f74a0b68..4395ff914 100644 --- a/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js +++ b/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js @@ -18,6 +18,10 @@ */ $(document).ready(function() { + // manage refund options checkboxes as per the refund paramenters + if ($('#order_return_form .table input[name^="refund_amounts"]').length) { + manageRefundOptions(); + } // initialize tootip for room price if ($('#rooms_refund_info .price_info').length) { @@ -91,32 +95,38 @@ $(document).ready(function() { }); $(document).on('keyup', '#order_return_form .table input[name^="refund_amounts"]', function() { - let refundAmountInputs = $('#order_return_form .table input[name^="refund_amounts"]'); + manageRefundOptions(); + }); +}); + +// This function manages (Enable/disable) the refund options check-boxes according to the refund parameters like refund amount +function manageRefundOptions() +{ + let refundAmountInputs = $('#order_return_form .table input[name^="refund_amounts"]'); + + let disableRefundOptions = false; + $(refundAmountInputs).each(function(index, element) { + let val = parseFloat($(element).val().trim()); + if (isNaN(val)) { // if at least one amount input is empty + disableRefundOptions = true; + return; + } + }); - let disableRefundOptions = false; + if (!disableRefundOptions) { + let hasAllZero = true; $(refundAmountInputs).each(function(index, element) { let val = parseFloat($(element).val().trim()); - if (isNaN(val)) { // if at least one amount input is empty - disableRefundOptions = true; + if (val != 0) { + hasAllZero = false; return; } }); - if (!disableRefundOptions) { - let hasAllZero = true; - $(refundAmountInputs).each(function(index, element) { - let val = parseFloat($(element).val().trim()); - if (val != 0) { - hasAllZero = false; - return; - } - }); - - if (hasAllZero) { // if all amount inputs are 0 - disableRefundOptions = true; - } + if (hasAllZero) { // if all amount inputs are 0 + disableRefundOptions = true; } + } - $('#generateCreditSlip, #refundTransactionAmount, #generateDiscount').attr('disabled', disableRefundOptions); - }); -}); \ No newline at end of file + $('#generateCreditSlip, #refundTransactionAmount, #generateDiscount').attr('disabled', disableRefundOptions); +} diff --git a/modules/hotelreservationsystem/views/templates/admin/order_refund_requests/helpers/view/view.tpl b/modules/hotelreservationsystem/views/templates/admin/order_refund_requests/helpers/view/view.tpl index 8ed126d27..8c74600fb 100644 --- a/modules/hotelreservationsystem/views/templates/admin/order_refund_requests/helpers/view/view.tpl +++ b/modules/hotelreservationsystem/views/templates/admin/order_refund_requests/helpers/view/view.tpl @@ -57,6 +57,14 @@
    +
    +
    + {l s='Order Id' mod='hotelreservationsystem'} : +
    + +
    {l s='Total order amount' mod='hotelreservationsystem'} : @@ -368,4 +376,4 @@
    -
    \ No newline at end of file +
    diff --git a/themes/hotel-reservation-theme/history.tpl b/themes/hotel-reservation-theme/history.tpl index b6eeee269..4944af2e7 100644 --- a/themes/hotel-reservation-theme/history.tpl +++ b/themes/hotel-reservation-theme/history.tpl @@ -147,6 +147,7 @@ {addJsDefL name=refund_request_sending_error}{l s='Some error occurred while processing request for booking cancelation.' js=1}{/addJsDefL} {addJsDefL name=no_bookings_selected}{l s='No rooms selected. Please select at least one room.' js=1}{/addJsDefL} {addJsDefL name=refund_request_success_txt}{l s='Request for booking cancelation is successffully created.' js=1}{/addJsDefL} + {addJsDefL name=cancellation_success_txt}{l s='Your booking is successffully cancelled.' js=1}{/addJsDefL} {addJsDefL name=cancel_req_txt}{l s='Cancel Request' js=1}{/addJsDefL} {addJsDefL name=cancel_booking_txt}{l s='Cancel Bookings' js=1}{/addJsDefL} -{/strip} \ No newline at end of file +{/strip} diff --git a/themes/hotel-reservation-theme/js/history.js b/themes/hotel-reservation-theme/js/history.js index 943c1e3bc..7f6cc5d36 100644 --- a/themes/hotel-reservation-theme/js/history.js +++ b/themes/hotel-reservation-theme/js/history.js @@ -276,7 +276,12 @@ $(document).ready(function(){ success:function(data) { if (data.status == '1') { $(".roomRequestForRefund").parent().html('

    '+req_sent_msg+'

    '); - showSuccessMessage(refund_request_success_txt); + + if (data.has_cancelled == 1) { + showSuccessMessage(cancellation_success_txt); + } else { + showSuccessMessage(refund_request_success_txt); + } $('.bookings_to_refund:checked').prop('disabled', true); diff --git a/themes/hotel-reservation-theme/order-detail.tpl b/themes/hotel-reservation-theme/order-detail.tpl index e6a88a799..f5ea4a25c 100644 --- a/themes/hotel-reservation-theme/order-detail.tpl +++ b/themes/hotel-reservation-theme/order-detail.tpl @@ -135,7 +135,7 @@
    {if $refund_allowed} - {if !$hasCompletelyRefunded} + {if !$completeRefundRequestOrCancel} {l s='Cancel Bookings'} {/if} @@ -549,17 +549,15 @@
    - {if $refund_allowed && $non_requested_rooms} + {if $refund_allowed && !$completeRefundRequestOrCancel}
    - {l s='Select rooms for which you want to cancel bookings. Additional facilities for cancelled rooms will be cancelled automatically.'} + {l s='Select rooms for which you want to cancel bookings. Services for cancelled rooms will be cancelled automatically.'}
    - {if !$hasCompletelyRefunded} -
    -
    - -
    -
    - {/if} +
    +
    + +
    +
    {/if} @@ -713,4 +711,4 @@
    -
    \ No newline at end of file +