From e910d33cd6f15214f82deb6dadd83ca6d8ea1885 Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Thu, 19 Jan 2023 16:53:19 +0530 Subject: [PATCH] Add credit slip to voucher flow --- .../controllers/orders/helpers/view/view.tpl | 58 +++ .../slip/_display_voucher_link.tpl | 22 ++ .../controllers/slip/_redeem_status.tpl | 24 ++ .../controllers/slip/_status_change_link.tpl | 23 ++ classes/order/OrderReturn.php | 348 +++++++++--------- classes/order/OrderSlip.php | 103 +++++- controllers/admin/AdminSlipController.php | 95 ++++- controllers/front/OrderDetailController.php | 2 +- controllers/front/OrderSlipController.php | 30 ++ install/data/db_structure.sql | 4 + js/admin/orders.js | 17 +- mails/en/credit_slip_voucher.html | 118 ++++++ mails/en/credit_slip_voucher.txt | 16 + mails/en/order_refund_pending_admin.html | 4 +- mails/en/order_refund_pending_admin.txt | 4 +- .../AdminOrderRefundRequestsController.php | 24 +- .../views/js/admin/wk_refund_request.js | 6 +- .../helpers/view/view.tpl | 65 +++- themes/hotel-reservation-theme/order-slip.tpl | 37 +- 19 files changed, 780 insertions(+), 220 deletions(-) create mode 100644 admin/themes/default/template/controllers/slip/_display_voucher_link.tpl create mode 100644 admin/themes/default/template/controllers/slip/_redeem_status.tpl create mode 100644 admin/themes/default/template/controllers/slip/_status_change_link.tpl create mode 100644 mails/en/credit_slip_voucher.html create mode 100644 mails/en/credit_slip_voucher.txt 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 37c51eb1e..87e9c102f 100644 --- a/admin/themes/default/template/controllers/orders/helpers/view/view.tpl +++ b/admin/themes/default/template/controllers/orders/helpers/view/view.tpl @@ -949,6 +949,64 @@ + {if is_array($returns) && count($returns)} +
+
+ {l s='Refunds'} +
+ + + + + + + + + {foreach from=$returns item=return_info} + + + + + {/foreach} + +
{l s='Refund ID'}{l s='Status'}
+ #{$return_info.id_order_return} + + {capture name=refund_status} + {if isset($return_info.payment_mode) && $return_info.payment_mode != ''}{l s='Payment Mode: '}{$return_info.payment_mode}
{/if} + {if isset($return_info.id_transaction) && $return_info.id_transaction != ''}{l s='Transaction ID: '}{$return_info.id_transaction}
{/if} + {if isset($return_info.id_return_type) && isset($return_info.return_type) && $return_info.id_return_type && $return_info.return_type} + {if $return_info.return_type == OrderReturn::RETURN_TYPE_CART_RULE} + {l s='Voucher ID: '} + + #{$return_info.id_return_type} + + {elseif $return_info.return_type == OrderReturn::RETURN_TYPE_ORDER_SLIP} + {l s='Credit Slip ID: '} + #{$return_info.id_return_type} + + {l s='Download' mod='hotelreservationsystem'} + + {/if} +
+ {/if} + {if isset($return_info.id_cart_rule) && $return_info.id_cart_rule} + {l s='Voucher ID: '} + + #{$return_info.id_cart_rule} + +
+ {/if} + {/capture} + + {if $smarty.capture.refund_status|trim != ''} + {$smarty.capture.refund_status} + {else} + {$return_info.state_name} + {/if} +
+
+ {/if} {hook h="displayAdminOrderRight" id_order=$order->id} diff --git a/admin/themes/default/template/controllers/slip/_display_voucher_link.tpl b/admin/themes/default/template/controllers/slip/_display_voucher_link.tpl new file mode 100644 index 000000000..9c65ed59a --- /dev/null +++ b/admin/themes/default/template/controllers/slip/_display_voucher_link.tpl @@ -0,0 +1,22 @@ +{** + * 2010-2023 Webkul. + * + * NOTICE OF LICENSE + * + * All right is reserved, + * Please go through LICENSE.txt file inside our module + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade this module to newer + * versions in the future. If you wish to customize this module for your + * needs please refer to CustomizationPolicy.txt file inside our module for more information. + * + * @author Webkul IN + * @copyright 2010-2022 Webkul IN + * @license LICENSE.txt + *} + + + #{$id_cart_rule} + diff --git a/admin/themes/default/template/controllers/slip/_redeem_status.tpl b/admin/themes/default/template/controllers/slip/_redeem_status.tpl new file mode 100644 index 000000000..4d4b54d0a --- /dev/null +++ b/admin/themes/default/template/controllers/slip/_redeem_status.tpl @@ -0,0 +1,24 @@ +{** + * 2010-2022 Webkul. + * + * NOTICE OF LICENSE + * + * All right is reserved, + * Please go through LICENSE.txt file inside our module + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade this module to newer + * versions in the future. If you wish to customize this module for your + * needs please refer to CustomizationPolicy.txt file inside our module for more information. + * + * @author Webkul IN + * @copyright 2010-2022 Webkul IN + * @license LICENSE.txt + *} + +{if $redeem_status == OrderSlip::REDEEM_STATUS_REDEEMED} + {l s='Redeemed'} +{else} + {l s='Active'} +{/if} diff --git a/admin/themes/default/template/controllers/slip/_status_change_link.tpl b/admin/themes/default/template/controllers/slip/_status_change_link.tpl new file mode 100644 index 000000000..958a76581 --- /dev/null +++ b/admin/themes/default/template/controllers/slip/_status_change_link.tpl @@ -0,0 +1,23 @@ +{** + * 2010-2023 Webkul. + * + * NOTICE OF LICENSE + * + * All right is reserved, + * Please go through LICENSE.txt file inside our module + * + * DISCLAIMER + * + * Do not edit or add to this file if you wish to upgrade this module to newer + * versions in the future. If you wish to customize this module for your + * needs please refer to CustomizationPolicy.txt file inside our module for more information. + * + * @author Webkul IN + * @copyright 2010-2022 Webkul IN + * @license LICENSE.txt + *} + + + + {l s='Change Status'} + diff --git a/classes/order/OrderReturn.php b/classes/order/OrderReturn.php index 89b94ea76..bd06ec1c4 100644 --- a/classes/order/OrderReturn.php +++ b/classes/order/OrderReturn.php @@ -26,6 +26,9 @@ class OrderReturnCore extends ObjectModel { + /** @var int */ + public $id_order_return; + /** @var int */ public $id_customer; @@ -48,12 +51,22 @@ class OrderReturnCore extends ObjectModel /** @var int if request raised by the admin */ public $by_admin; + /** @var int id_cart_rule or id_order_slip */ + public $id_return_type; + + /** @var int whether $id_return_type is cart_rule or order_slip */ + public $return_type; + /** @var string Object creation date */ public $date_add; /** @var string Object last modification date */ public $date_upd; + /** possible values for $return_type */ + const RETURN_TYPE_CART_RULE = 1; + const RETURN_TYPE_ORDER_SLIP = 2; + /** * @see ObjectModel::$definition */ @@ -69,6 +82,8 @@ class OrderReturnCore extends ObjectModel 'refunded_amount' => array('type' => self::TYPE_FLOAT), 'state' => array('type' => self::TYPE_INT), 'by_admin' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'id_return_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'return_type' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), ), @@ -232,14 +247,16 @@ class OrderReturnCore extends ObjectModel if (!$context) { $context = Context::getContext(); } - $data = Db::getInstance()->executeS(' - SELECT * - FROM `'._DB_PREFIX_.'order_return` - WHERE `id_customer` = '.(int)$customer_id. - ($only_customer ? ' AND `by_admin` = 0' : ''). - ($order_id ? ' AND `id_order` = '.(int)$order_id : ''). - ($no_denied ? ' AND `state` != 4' : '').' - ORDER BY `date_add` DESC'); + $sql = 'SELECT * + FROM `'._DB_PREFIX_.'order_return` orr + LEFT JOIN `'._DB_PREFIX_.'order_slip` ors + ON (ors.`id_order_slip` = orr.`id_return_type` AND orr.`return_type` = '.(int) self::RETURN_TYPE_ORDER_SLIP.') + WHERE orr.`id_customer` = '.(int)$customer_id. + ($only_customer ? ' AND orr.`by_admin` = 0' : ''). + ($order_id ? ' AND orr.`id_order` = '.(int)$order_id : ''). + ($no_denied ? ' AND orr.`state` != 4' : '').' + ORDER BY orr.`date_add` DESC'; + $data = Db::getInstance()->executeS($sql); foreach ($data as $k => $or) { $state = new OrderReturnState($or['state']); $data[$k]['state_name'] = $state->name[$context->language->id]; @@ -373,144 +390,112 @@ class OrderReturnCore extends ObjectModel /** * Sets the new order return state * @param int $newOrderReturnState - * @param int/object $idOrderReturn */ - public function changeIdOrderReturnState($newOrderReturnState, $idOrderReturn, $idLang = 0) + public function changeIdOrderReturnState($newOrderReturnState, $idLang = 0) { - if (Validate::isLoadedObject($objOrderReturn = new OrderReturn((int)$idOrderReturn))) { - $objOrder = new Order($objOrderReturn->id_order); + $objOrder = new Order($this->id_order); + if (!$idLang) { + $idLang = $objOrder->id_lang; + } + if (Validate::isLoadedObject( + $objOrderReturnState = new OrderReturnState((int)$newOrderReturnState, $idLang) + )) { + if ($this->state != $newOrderReturnState) { + $this->state = $newOrderReturnState; + $this->save(); - if (!$idLang) { - $idLang = $objOrder->id_lang; - } - if (Validate::isLoadedObject( - $objOrderReturnState = new OrderReturnState((int)$newOrderReturnState, $idLang) - )) { - if ($objOrderReturn->state != $newOrderReturnState) { - $objOrderReturn->state = $newOrderReturnState; - $objOrderReturn->save(); + if ($objOrderReturnState->send_email_to_customer + || $objOrderReturnState->send_email_to_superadmin + || $objOrderReturnState->send_email_to_employee + || $objOrderReturnState->send_email_to_hotelier + ) { + // Lets create data for the email templates + $objMail = new Mail(); + $idHotel = 0; - if ($objOrderReturnState->send_email_to_customer - || $objOrderReturnState->send_email_to_superadmin - || $objOrderReturnState->send_email_to_employee - || $objOrderReturnState->send_email_to_hotelier - ) { - // Lets create data for the email templates - $objMail = new Mail(); - $idHotel = 0; + $data = array ( + '{status_name}' => $objOrderReturnState->name, + '{status_color}' => $objOrderReturnState->color, + '{order_reference}' => $objOrder->reference, + '{order_date}' => date('Y-m-d h:i:s', strtotime($objOrder->date_add)), + '{refunded_amount}' => Tools::displayPrice($this->refunded_amount, new Currency($objOrder->id_currency)), + '{payment_mode}' => $this->payment_mode, + '{id_transaction}' => $this->id_transaction, + ); - $data = array ( - '{status_name}' => $objOrderReturnState->name, - '{status_color}' => $objOrderReturnState->color, - '{order_reference}' => $objOrder->reference, - '{order_date}' => date('Y-m-d h:i:s', strtotime($objOrder->date_add)), - '{refunded_amount}' => Tools::displayPrice($objOrderReturn->refunded_amount, new Currency($objOrder->id_currency)), - '{payment_mode}' => $objOrderReturn->payment_mode, - '{id_transaction}' => $objOrderReturn->id_transaction, - ); - - // if mail is true for the customer then send mail to customer with selected template - $objCustomer = new Customer($objOrderReturn->id_customer); - if ($objOrderReturnState->send_email_to_customer && $objOrderReturnState->customer_template) { - if ($refundReqBookings = $objOrderReturn->getOrderRefundRequestedBookings( - $objOrderReturn->id_order, - $objOrderReturn->id, - 0, - 1 - )) { - $idHotel = reset($refundReqBookings)['id_hotel']; - } - - $refBookHtml = $objMail->getEmailTemplateContent('refund_request_detail_customer', Mail::TYPE_HTML, $refundReqBookings); - $refBookTxt = $objMail->getEmailTemplateContent('refund_request_detail_customer', Mail::TYPE_TEXT, $refundReqBookings); - - $data['{refundBookingHtml}'] = $refBookHtml; - $data['{refundBookingTxt}'] = $refBookTxt; - - // send customer information - $link = new Link(); - $data['{refund_reqests_url}'] = $link->getPageLink('order-follow'); - $data['{firstname}'] = $objCustomer->firstname; - $data['{lastname}'] = $objCustomer->lastname; - - Mail::Send( - (int)$idLang, - $objOrderReturnState->customer_template, - $objOrderReturnState->name, - $data, - $objCustomer->email, - $objCustomer->firstname.' '.$objCustomer->lastname, - null, - null, - null, - null, - _PS_MAIL_DIR_, - false, - (int)$objOrder->id_shop - ); + // if mail is true for the customer then send mail to customer with selected template + $objCustomer = new Customer($this->id_customer); + if ($objOrderReturnState->send_email_to_customer && $objOrderReturnState->customer_template) { + if ($refundReqBookings = $this->getOrderRefundRequestedBookings( + $this->id_order, + $this->id, + 0, + 1 + )) { + $idHotel = reset($refundReqBookings)['id_hotel']; } - if ($objOrderReturnState->admin_template) { - if ($refundReqBookings = $objOrderReturn->getOrderRefundRequestedBookings( - $objOrderReturn->id_order, - $objOrderReturn->id - )) { - $idHotel = $refundReqBookings[0]['id_hotel']; - } + $refBookHtml = $objMail->getEmailTemplateContent('refund_request_detail_customer', Mail::TYPE_HTML, $refundReqBookings); + $refBookTxt = $objMail->getEmailTemplateContent('refund_request_detail_customer', Mail::TYPE_TEXT, $refundReqBookings); - $refBookHtml = $objMail->getEmailTemplateContent('refund_request_detail_admin', Mail::TYPE_HTML, $refundReqBookings); - $refBookTxt = $objMail->getEmailTemplateContent('refund_request_detail_admin', Mail::TYPE_TEXT, $refundReqBookings); + $data['{refundBookingHtml}'] = $refBookHtml; + $data['{refundBookingTxt}'] = $refBookTxt; - $data['{cancelation_reason}'] = $objOrderReturn->question; - $data['{refundBookingHtml}'] = $refBookHtml; - $data['{refundBookingTxt}'] = $refBookTxt; + // send customer information + $link = new Link(); + $data['{refund_reqests_url}'] = $link->getPageLink('order-follow'); + $data['{firstname}'] = $objCustomer->firstname; + $data['{lastname}'] = $objCustomer->lastname; - // send mail to the super admin - if ($objOrderReturnState->send_email_to_superadmin) { - // send superadmin information - if (Validate::isLoadedObject($superAdmin = new Employee(_PS_ADMIN_PROFILE_))) { - if (Validate::isEmail($superAdmin->email)) { - $data['{customer_name}'] = $objCustomer->firstname.' '.$objCustomer->lastname; - $data['{customer_email}'] = $objCustomer->email; - $data['{firstname}'] = $superAdmin->firstname; - $data['{lastname}'] = $superAdmin->lastname; + Mail::Send( + (int)$idLang, + $objOrderReturnState->customer_template, + $objOrderReturnState->name, + $data, + $objCustomer->email, + $objCustomer->firstname.' '.$objCustomer->lastname, + null, + null, + null, + null, + _PS_MAIL_DIR_, + false, + (int)$objOrder->id_shop + ); + } - Mail::Send( - (int)$idLang, - $objOrderReturnState->admin_template, - $objOrderReturnState->name, - $data, - $superAdmin->email, - $superAdmin->firstname.' '.$superAdmin->lastname, - null, - null, - null, - null, - _PS_MAIL_DIR_, - false, - (int)$objOrder->id_shop - ); - } - } - } - if ($idHotel - && Validate::isLoadedObject($objHotel = new HotelBranchInformation($idHotel)) - ) { - // send mail to the hotelier - if ($objOrderReturnState->send_email_to_hotelier) { + if ($objOrderReturnState->admin_template) { + if ($refundReqBookings = $this->getOrderRefundRequestedBookings( + $this->id_order, + $this->id + )) { + $idHotel = $refundReqBookings[0]['id_hotel']; + } + + $refBookHtml = $objMail->getEmailTemplateContent('refund_request_detail_admin', Mail::TYPE_HTML, $refundReqBookings); + $refBookTxt = $objMail->getEmailTemplateContent('refund_request_detail_admin', Mail::TYPE_TEXT, $refundReqBookings); + + $data['{cancelation_reason}'] = $this->question; + $data['{refundBookingHtml}'] = $refBookHtml; + $data['{refundBookingTxt}'] = $refBookTxt; + + // send mail to the super admin + if ($objOrderReturnState->send_email_to_superadmin) { + // send superadmin information + if (Validate::isLoadedObject($superAdmin = new Employee(_PS_ADMIN_PROFILE_))) { + if (Validate::isEmail($superAdmin->email)) { $data['{customer_name}'] = $objCustomer->firstname.' '.$objCustomer->lastname; $data['{customer_email}'] = $objCustomer->email; - $data['{firstname}'] = ''; - $data['{lastname}'] = ''; - $data['{email}'] = $objHotel->email; + $data['{firstname}'] = $superAdmin->firstname; + $data['{lastname}'] = $superAdmin->lastname; Mail::Send( (int)$idLang, $objOrderReturnState->admin_template, $objOrderReturnState->name, $data, - $objHotel->email, - null, + $superAdmin->email, + $superAdmin->firstname.' '.$superAdmin->lastname, null, null, null, @@ -520,38 +505,66 @@ class OrderReturnCore extends ObjectModel (int)$objOrder->id_shop ); } + } + } + if ($idHotel + && Validate::isLoadedObject($objHotel = new HotelBranchInformation($idHotel)) + ) { + // send mail to the hotelier + if ($objOrderReturnState->send_email_to_hotelier) { + $data['{customer_name}'] = $objCustomer->firstname.' '.$objCustomer->lastname; + $data['{customer_email}'] = $objCustomer->email; + $data['{firstname}'] = ''; + $data['{lastname}'] = ''; + $data['{email}'] = $objHotel->email; - // send mail to the employee - if ($objOrderReturnState->send_email_to_employee) { - if ($htlAccesses = $objHotel->getHotelAccess($idHotel)) { - $data['{customer_name}'] = $objCustomer->firstname.' '.$objCustomer->lastname; - $data['{customer_email}'] = $objCustomer->email; - foreach ($htlAccesses as $access) { - if ($access['id_profile'] != _PS_ADMIN_PROFILE_) { - if ($htlEmployees = Employee::getEmployeesByProfile($access['id_profile'])) { - foreach ($htlEmployees as $empl) { - if (Validate::isEmail($empl['email'])) { - // send hotel manager (employee) have permission for this hotel - $data['{firstname}'] = $empl['firstname']; - $data['{lastname}'] = $empl['lastname']; - $data['{email}'] = $empl['email']; + Mail::Send( + (int)$idLang, + $objOrderReturnState->admin_template, + $objOrderReturnState->name, + $data, + $objHotel->email, + null, + null, + null, + null, + null, + _PS_MAIL_DIR_, + false, + (int)$objOrder->id_shop + ); + } - Mail::Send( - (int)$idLang, - $objOrderReturnState->admin_template, - $objOrderReturnState->name, - $data, - $empl['email'], - $empl['firstname'].' '.$empl['lastname'], - null, - null, - null, - null, - _PS_MAIL_DIR_, - false, - (int)$objOrder->id_shop - ); - } + // send mail to the employee + if ($objOrderReturnState->send_email_to_employee) { + if ($htlAccesses = $objHotel->getHotelAccess($idHotel)) { + $data['{customer_name}'] = $objCustomer->firstname.' '.$objCustomer->lastname; + $data['{customer_email}'] = $objCustomer->email; + foreach ($htlAccesses as $access) { + if ($access['id_profile'] != _PS_ADMIN_PROFILE_) { + if ($htlEmployees = Employee::getEmployeesByProfile($access['id_profile'])) { + foreach ($htlEmployees as $empl) { + if (Validate::isEmail($empl['email'])) { + // send hotel manager (employee) have permission for this hotel + $data['{firstname}'] = $empl['firstname']; + $data['{lastname}'] = $empl['lastname']; + $data['{email}'] = $empl['email']; + + Mail::Send( + (int)$idLang, + $objOrderReturnState->admin_template, + $objOrderReturnState->name, + $data, + $empl['email'], + $empl['firstname'].' '.$empl['lastname'], + null, + null, + null, + null, + _PS_MAIL_DIR_, + false, + (int)$objOrder->id_shop + ); } } } @@ -561,18 +574,21 @@ class OrderReturnCore extends ObjectModel } } } - - // executes hook - Hook::exec( - 'actionOrderReFundStatusPostUpdate', - array( - 'new_order_return_status' => $newOrderReturnState, - 'id_order_return' => (int)$idOrderReturn - ) - ); } + + // executes hook + Hook::exec( + 'actionOrderReFundStatusPostUpdate', + array( + 'new_order_return_status' => $newOrderReturnState, + 'id_order_return' => (int) $this->id_order_return, + ) + ); + + return true; } } + return false; } diff --git a/classes/order/OrderSlip.php b/classes/order/OrderSlip.php index f64269d75..ed662e6bf 100644 --- a/classes/order/OrderSlip.php +++ b/classes/order/OrderSlip.php @@ -27,7 +27,7 @@ class OrderSlipCore extends ObjectModel { /** @var int */ - public $id; + public $id_order_slip; /** @var int */ public $id_customer; @@ -62,6 +62,12 @@ class OrderSlipCore extends ObjectModel /** @var int */ public $partial; + /** @var int */ + public $redeem_status = self::REDEEM_STATUS_ACTIVE; + + /** @var int */ + public $id_cart_rule; + /** @var string Object creation date */ public $date_add; @@ -71,6 +77,9 @@ class OrderSlipCore extends ObjectModel /** @var int */ public $order_slip_type = 0; + const REDEEM_STATUS_ACTIVE = 1; + const REDEEM_STATUS_REDEEMED = 2; + /** * @see ObjectModel::$definition */ @@ -90,6 +99,8 @@ class OrderSlipCore extends ObjectModel 'shipping_cost_amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), 'amount' => array('type' => self::TYPE_FLOAT, 'validate' => 'isFloat'), 'partial' => array('type' => self::TYPE_INT), + 'redeem_status' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), + 'id_cart_rule' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDate'), 'order_slip_type' => array('type' => self::TYPE_INT, 'validate' => 'isInt'), @@ -336,6 +347,7 @@ class OrderSlipCore extends ObjectModel $order_slip->{'total_products_tax_'.$inc_or_ex_1} = 0; $order_slip->{'total_products_tax_'.$inc_or_ex_2} = 0; + $total_products = array(); foreach ($booking_list as &$booking) { $objHtlBooking = new HotelBookingDetail($booking['id_htl_booking']); $order_detail = new OrderDetail((int)$objHtlBooking->id_order_detail); @@ -543,6 +555,95 @@ class OrderSlipCore extends ObjectModel return $ecotax_detail; } + /** + * generate voucher and return id of the created rule if successful, false otherwise + */ + public function generateVoucher($sendMail = true) + { + if (!Validate::isLoadedObject($this)) { + return false; + } + + if ($this->redeem_status != self::REDEEM_STATUS_ACTIVE) { + return false; + } + + $objOrder = new Order($this->id_order); + if (!Validate::isLoadedObject($objOrder)) { + return false; + } + + $objCustomer = new Customer($this->id_customer); + if (!Validate::isLoadedObject($objCustomer)) { + return false; + } + + $context = Context::getContext(); + $objCartRule = new CartRule(); + $idsLanguage = Language::getIDs(); + + $creditSlipPrefix = Configuration::get('PS_CREDIT_SLIP_PREFIX', $context->language->id); + $creditSlipID = sprintf(('%1$s%2$06d'), $creditSlipPrefix, (int) $this->id_order_slip); + + $dateFrom = $this->date_add; + $dateTo = date('Y-m-d H:i:s', strtotime($dateFrom) + (3600 * 24 * 365.25)); /* 1 year */ + + foreach ($idsLanguage as $idLang) { + $objCartRule->name[$idLang] = sprintf('Voucher for credit slip #%s', $creditSlipID); + } + + $objCartRule->description = sprintf('Order: #%s', $objOrder->id); + $objCartRule->code = 'CS'.(int) ($this->id_order_slip).'C'.(int) ($objCustomer->id).'O'.(int) ($objOrder->id); + $objCartRule->quantity = 1; + $objCartRule->quantity_per_user = 1; + $objCartRule->id_customer = $objCustomer->id; + $objCartRule->date_from = $dateFrom; + $objCartRule->date_to = $dateTo; + $objCartRule->highlight = 1; + $objCartRule->active = 1; + $objCartRule->reduction_amount = $this->amount; + $objCartRule->reduction_tax = true; + $objCartRule->minimum_amount_currency = $objOrder->id_currency; + $objCartRule->reduction_currency = $objOrder->id_currency; + + if (!$objCartRule->save()) { + return false; + } + + $this->redeem_status = self::REDEEM_STATUS_REDEEMED; + $this->id_cart_rule = (int) $objCartRule->id; + $this->save(); + + if ($sendMail) { + $objCartRule = new CartRule($this->id_cart_rule); + $objCustomer = new Customer($objCartRule->id_customer); + + $objCurrency = new Currency($objCartRule->reduction_currency, $context->language->id); + $mailVars['{firstname}'] = $objCustomer->firstname; + $mailVars['{lastname}'] = $objCustomer->lastname; + $mailVars['{credit_slip_id}'] = $creditSlipID; + $mailVars['{voucher_code}'] = $objCartRule->code; + $mailVars['{voucher_amount}'] = Tools::displayPrice($objCartRule->reduction_amount, $objCurrency, false); + + Mail::Send( + $context->language->id, + 'credit_slip_voucher', + sprintf(Mail::l('New voucher for your credit slip #%s', $context->language->id), $creditSlipID), + $mailVars, + $objCustomer->email, + $objCustomer->firstname.' '.$objCustomer->lastname, + null, + null, + null, + null, + _PS_MAIL_DIR_, + true + ); + } + + return $this->id_cart_rule; + } + public function getWsOrderSlipDetails() { $query = 'SELECT id_order_slip as id, id_order_detail, product_quantity, amount_tax_excl, amount_tax_incl diff --git a/controllers/admin/AdminSlipController.php b/controllers/admin/AdminSlipController.php index d17cd3252..a64d044c2 100644 --- a/controllers/admin/AdminSlipController.php +++ b/controllers/admin/AdminSlipController.php @@ -34,11 +34,14 @@ class AdminSlipControllerCore extends AdminController $this->bootstrap = true; $this->table = 'order_slip'; $this->className = 'OrderSlip'; + $this->list_no_link = true; $this->_select = ' o.`id_shop`'; $this->_join .= ' LEFT JOIN '._DB_PREFIX_.'orders o ON (o.`id_order` = a.`id_order`)'; $this->_group = ' GROUP BY a.`id_order_slip`'; + $this->addRowAction('statusChange'); + $this->fields_list = array( 'id_order_slip' => array( 'title' => $this->l('ID'), @@ -63,7 +66,26 @@ class AdminSlipControllerCore extends AdminController 'callback' => 'printPDFIcons', 'orderby' => false, 'search' => false, - 'remove_onclick' => true) + 'remove_onclick' => true + ), + 'redeem_status' => array( + 'title' => $this->l('Status'), + 'type' => 'select', + 'list' => array( + OrderSlip::REDEEM_STATUS_ACTIVE => $this->l('Active'), + OrderSlip::REDEEM_STATUS_REDEEMED => $this->l('Redeemed'), + ), + 'align' => 'center', + 'filter_key' => 'a!redeem_status', + 'callback' => 'displayRedeemStatus', + 'class' => 'fixed-width-md', + ), + 'id_cart_rule' => array( + 'title' => $this->l('Voucher'), + 'align' => 'center', + 'callback' => 'displayVoucherLink', + 'class' => 'fixed-width-lg', + ), ); $this->_select = 'a.id_order_slip AS id_pdf'; @@ -162,6 +184,38 @@ class AdminSlipControllerCore extends AdminController } } + public function processStatusChange() + { + $idOrderSlip = Tools::getValue('id_order_slip'); + $objOrderSlip = new OrderSlip($idOrderSlip); + + if (!Validate::isLoadedObject($objOrderSlip)) { + $this->errors[] = $this->l('The credit slip can not be loaded.'); + } elseif ($objOrderSlip->redeem_status != OrderSlip::REDEEM_STATUS_ACTIVE) { + $this->errors[] = $this->l('The status for this credit slip can not be changed.'); + } else { + $objOrder = new Order($objOrderSlip->id_order); + $objCustomer = new Customer($objOrderSlip->id_customer); + + if (!Validate::isLoadedObject($objOrder)) { + $this->errors[] = $this->l('The related order for this credit slip can not be loaded.'); + } + + if (!Validate::isLoadedObject($objCustomer)) { + $this->errors[] = $this->l('The related customer for this credit slip can not be loaded.'); + } + } + + if (!count($this->errors)) { + $objOrderSlip->redeem_status = OrderSlip::REDEEM_STATUS_REDEEMED; + if ($objOrderSlip->save()) { + Tools::redirectAdmin(self::$currentIndex.'&token='.$this->token.'&conf=4'); + } + + $this->errors[] = $this->l('Something went wrong while changing status.'); + } + } + public function initContent() { $this->initTabModuleList(); @@ -202,4 +256,43 @@ class AdminSlipControllerCore extends AdminController return $this->createTemplate('_print_pdf_icon.tpl')->fetch(); } + + public function displayRedeemStatus($redeemStatus, $row) + { + $this->context->smarty->assign(array( + 'redeem_status' => $redeemStatus, + )); + + return $this->createTemplate('_redeem_status.tpl')->fetch(); + } + + public function displayVoucherLink($idCartRule, $row) + { + if ($row['redeem_status'] == OrderSlip::REDEEM_STATUS_REDEEMED && $idCartRule) { + $this->context->smarty->assign(array( + 'id_cart_rule' => (int) $idCartRule, + )); + + return $this->createTemplate('_display_voucher_link.tpl')->fetch(); + } + + return '--'; + } + + public function displayStatusChangeLink($token = null, $id) + { + $objOrderSlip = new OrderSlip($id); + if ($objOrderSlip->redeem_status != OrderSlip::REDEEM_STATUS_REDEEMED) { + $statusChangeLink = self::$currentIndex.'&'.$this->identifier.'='.$id.'&action=statusChange'. + '&token='.($token != null ? $token : $this->token); + + $this->context->smarty->assign(array( + 'status_change_link' => $statusChangeLink, + )); + + return $this->createTemplate('_status_change_link.tpl')->fetch(); + } + + return '--'; + } } diff --git a/controllers/front/OrderDetailController.php b/controllers/front/OrderDetailController.php index 120a32022..413ea2a5b 100644 --- a/controllers/front/OrderDetailController.php +++ b/controllers/front/OrderDetailController.php @@ -246,7 +246,7 @@ class OrderDetailControllerCore extends FrontController } } // Emails to customer, admin on refund request state change - $objOrderReturn->changeIdOrderReturnState(OrderReturnState::ORDER_RETRUN_FIRST_STATUS, $objOrderReturn->id); + $objOrderReturn->changeIdOrderReturnState(Configuration::get('PS_ORS_PENDING')); die(json_encode(array('status' => 1))); } diff --git a/controllers/front/OrderSlipController.php b/controllers/front/OrderSlipController.php index 26a5372c8..2b33b6cad 100644 --- a/controllers/front/OrderSlipController.php +++ b/controllers/front/OrderSlipController.php @@ -53,4 +53,34 @@ class OrderSlipControllerCore extends FrontController $this->context->smarty->assign('ordersSlip', OrderSlip::getOrdersSlip((int)$this->context->cookie->id_customer)); $this->setTemplate(_PS_THEME_DIR_.'order-slip.tpl'); } + + public function postProcess() + { + if (Tools::isSubmit('generateVoucher')) { + $idOrderSlip = Tools::getValue('id_order_slip'); + $objOrderSlip = new OrderSlip($idOrderSlip); + if (!Validate::isLoadedObject($objOrderSlip)) { + $this->errors[] = Tools::displayError('The credit slip is invalid.'); + } elseif ($objOrderSlip->redeem_status == OrderSlip::REDEEM_STATUS_REDEEMED) { + $this->errors[] = Tools::displayError('The credit slip has already been redeemed.'); + } elseif ($objOrderSlip->id_customer != $this->context->customer->id) { + $this->errors[] = Tools::displayError('Invalid request.'); + } + + if (!count($this->errors)) { + if ($objOrderSlip->generateVoucher()) { + Tools::redirect($this->context->link->getPageLink( + $this->php_self, + $this->ssl, + $this->context->language->id, + 'confirmation=1' + )); + } + + $this->errors[] = Tools::displayError('The voucher code for this credit slip could not be generated.'); + } + } + + parent::postProcess(); + } } diff --git a/install/data/db_structure.sql b/install/data/db_structure.sql index 56750610c..5b04acd14 100644 --- a/install/data/db_structure.sql +++ b/install/data/db_structure.sql @@ -1304,6 +1304,8 @@ CREATE TABLE `PREFIX_order_return` ( `refunded_amount` decimal(20,6) NOT NULL DEFAULT '0.000000', `question` text NOT NULL, `by_admin` tinyint(1) unsigned NOT NULL DEFAULT '0', + `id_return_type` tinyint(1) unsigned NOT NULL DEFAULT '0', + `return_type` tinyint(1) unsigned NOT NULL DEFAULT '0', `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, PRIMARY KEY (`id_order_return`), @@ -1358,6 +1360,8 @@ CREATE TABLE `PREFIX_order_slip` ( `amount` DECIMAL(10,2) NOT NULL, `shipping_cost_amount` DECIMAL(10,2) NOT NULL, `partial` TINYINT(1) NOT NULL, + `redeem_status` TINYINT(1) NOT NULL DEFAULT '0', + `id_cart_rule` int(10) unsigned NOT NULL DEFAULT '0', `order_slip_type` TINYINT(1) unsigned NOT NULL DEFAULT '0', `date_add` datetime NOT NULL, `date_upd` datetime NOT NULL, diff --git a/js/admin/orders.js b/js/admin/orders.js index 1871bf66d..9cef75238 100644 --- a/js/admin/orders.js +++ b/js/admin/orders.js @@ -605,7 +605,6 @@ function init() $('.row-editing-warning').hide(); $('.cancel_product_change_link:visible').trigger('click'); closeAddProduct(); - refundFormStatus = 'closed'; /*By webkul*/ var tr_product = $(this).closest('.product-line-row'); @@ -931,26 +930,20 @@ function init() /* Refund system script */ var flagRefund = ''; -var refundFormStatus = 'closed'; $(document).ready(function() { + // Used for Cancel bookings/Initiate refund button $('#desc-order-standard_refund').click(function() { - $('.cancel_product_change_link:visible').trigger('click'); - - if (refundFormStatus == 'closed') { - $('.standard_refund_fields').fadeIn(); - refundFormStatus = 'open'; - } - closeAddProduct(); - if (order_discount_price) + $('.cancel_product_change_link:visible').trigger('click'); + if (order_discount_price) { actualizeTotalRefundVoucher(); - + } + $('.standard_refund_fields, .order_action').fadeIn(); scroll_if_anchor('#refundForm', 170); }); $('#cancelRefund').click(function() { $('.standard_refund_fields').hide(); - refundFormStatus = 'closed'; }); $('#desc-order-partial_refund').click(function() { diff --git a/mails/en/credit_slip_voucher.html b/mails/en/credit_slip_voucher.html new file mode 100644 index 000000000..2e09db6a4 --- /dev/null +++ b/mails/en/credit_slip_voucher.html @@ -0,0 +1,118 @@ + + + + + + Message from {shop_name} + + + + + + + + + + + + +
  + + + + + + + + + + + + + + + + + + + + + +
+ + Hi {firstname} {lastname}, + +
+ + + + + + +
  + +

+ VOUCHER GENERATED +

+ + Your voucher has been generated successfully against your credit slip #{credit_slip_id}. +

+ Voucher Code: {voucher_code} for an amount of {voucher_amount}.

+ To use this voucher just copy and paste this code during payment process for your next order. +
+
+
 
+
+
 
+ + \ No newline at end of file diff --git a/mails/en/credit_slip_voucher.txt b/mails/en/credit_slip_voucher.txt new file mode 100644 index 000000000..38bf3a5f8 --- /dev/null +++ b/mails/en/credit_slip_voucher.txt @@ -0,0 +1,16 @@ + +[/{shop_url}] + +Hi {firstname} {lastname}, + +VOUCHER GENERATED + +Your voucher has been generated successfully against your credit slip #{credit_slip_id}. + +VOUCHER CODE: {voucher_code} for an amount of {voucher_amount}. + +To use this voucher just copy and paste this code during payment process for your next +order. + +{shop_name} [/{shop_url}] powered by Webkul(tm) +[http://www.webkul.com/] diff --git a/mails/en/order_refund_pending_admin.html b/mails/en/order_refund_pending_admin.html index ae72fbae6..3c5a93547 100755 --- a/mails/en/order_refund_pending_admin.html +++ b/mails/en/order_refund_pending_admin.html @@ -73,7 +73,7 @@ Hi {firstname} {lastname},
- A request has been generated for the booking cancellation. + A request has been generated for booking cancellations.
@@ -104,7 +104,7 @@ -

Booking details

+

Requested Booking Cancellations

diff --git a/mails/en/order_refund_pending_admin.txt b/mails/en/order_refund_pending_admin.txt index 29b1acbbf..f520f617c 100755 --- a/mails/en/order_refund_pending_admin.txt +++ b/mails/en/order_refund_pending_admin.txt @@ -1,7 +1,7 @@ Message from {shop_name} Hi {firstname} {lastname}, -A request has been generated for the booking cancellation. +A request has been generated for booking cancellations. Order details @@ -9,7 +9,7 @@ Order: {order_reference} Placed on {order_date} Refund Status: {status_name} Cancelation Reason: {cancelation_reason} -Booking details +Requested Booking Cancellations Room Num Room Type diff --git a/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php b/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php index 547f992e5..88ce7db9c 100644 --- a/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php +++ b/modules/hotelreservationsystem/controllers/admin/AdminOrderRefundRequestsController.php @@ -46,7 +46,7 @@ class AdminOrderRefundRequestsController extends ModuleAdminController /*for showing status of booking with badge_danger or success*/ $this->fields_list = array( 'id_order' => array( - 'title' => $this->l('Id Order'), + 'title' => $this->l('Order ID'), 'align' => 'center', 'class' => 'fixed-width-xs', 'callback' => 'setOrderLink', @@ -164,12 +164,12 @@ class AdminOrderRefundRequestsController extends ModuleAdminController } $this->fields_list = array( 'id_order_return' => array( - 'title' => $this->l('Id'), + 'title' => $this->l('ID'), 'align' => 'center', 'class' => 'fixed-width-xs', ), 'id_order' => array( - 'title' => $this->l('Id Order'), + 'title' => $this->l('Order ID'), 'align' => 'center', 'class' => 'fixed-width-xs', 'callback' => 'setOrderLink', @@ -249,6 +249,7 @@ class AdminOrderRefundRequestsController extends ModuleAdminController $this->context->language->id), 'currentStateInfo' => (array) new OrderReturnState($objOrderReturn->state, $this->context->language->id), + 'current_id_lang' => $this->context->language->id, 'refundStatuses' => $refundStatuses, 'isRefundCompleted' => $objOrderReturn->hasBeenCompleted(), 'paymentMethods' => $paymentMethods, @@ -402,7 +403,7 @@ class AdminOrderRefundRequestsController extends ModuleAdminController $objOrderReturn->refunded_amount = $totalRefundedAmount; if ($objOrderReturn->save()) { // change state of the order refund - $objOrderReturn->changeIdOrderReturnState($idRefundState, $idOrderReturn); + $objOrderReturn->changeIdOrderReturnState($idRefundState); if ($objRefundState->refunded || $objRefundState->denied) { // check if order is paid the set status of the order to refunded @@ -434,6 +435,10 @@ class AdminOrderRefundRequestsController extends ModuleAdminController if (!$idCreditSlip = OrderSlip::create($objOrder, $bookingList, 0, 0, 0, 0)) { $this->errors[] = $this->l('A credit slip cannot be generated. '); } else { + $objOrderReturn->id_return_type = $idCreditSlip; + $objOrderReturn->return_type = OrderReturn::RETURN_TYPE_ORDER_SLIP; + $objOrderReturn->save(); + Hook::exec('actionOrderSlipAdd', array('order' => $objOrder, 'bookingList' => $bookingList)); @Mail::Send( @@ -452,13 +457,11 @@ class AdminOrderRefundRequestsController extends ModuleAdminController (int)$objOrder->id_shop ); } - } - - // Generate voucher - if (Tools::isSubmit('generateDiscount') && !count($this->errors)) { + } elseif (Tools::isSubmit('generateDiscount') && !count($this->errors)) { + // Generate voucher $cartrule = new CartRule(); $language_ids = Language::getIDs(); - $cartrule->description = sprintf($this->l('Credit card slip for order #%d'), $objOrder->id); + $cartrule->description = sprintf($this->l('Voucher for order #%d'), $objOrder->id); foreach ($language_ids as $id_lang) { // Define a temporary name $cartrule->name[$id_lang] = 'V0C'.(int)($objOrder->id_customer).'O'.(int)($objOrder->id); @@ -483,7 +486,8 @@ class AdminOrderRefundRequestsController extends ModuleAdminController if (!$cartrule->add()) { $this->errors[] = $this->errors('You cannot generate a voucher.'); } else { - $objOrderReturn->id_transaction = $cartrule->id; + $objOrderReturn->id_return_type = $cartrule->id; + $objOrderReturn->return_type = OrderReturn::RETURN_TYPE_CART_RULE; $objOrderReturn->save(); // Update the voucher code and name foreach ($language_ids as $id_lang) { diff --git a/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js b/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js index 1cda4111f..8652f0ea5 100644 --- a/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js +++ b/modules/hotelreservationsystem/views/js/admin/wk_refund_request.js @@ -42,11 +42,11 @@ $(document).ready(function() { } }); - $('#refundTransactionAmount, #generateDiscount').click(function() { + $('#generateCreditSlip, #generateDiscount').click(function() { if ($(this).is(':checked')) { - $('#refundTransactionAmount, #generateDiscount').prop('checked', false); + $('#generateCreditSlip, #generateDiscount').prop('checked', false); $(this).prop('checked', true); } - $('#refundTransactionAmount').change(); + $('#generateCreditSlip').change(); }); }); \ No newline at end of file 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 1f8639cd8..2442ace4e 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 @@ -159,28 +159,57 @@ {if $currentStateInfo['refunded']}
- {l s='Payment mode' mod='hotelreservationsystem'} : -
-
- {$orderReturnInfo['payment_mode']|escape:'html':'UTF-8'} -
-
-
-
- {l s='Transaction ID' mod='hotelreservationsystem'} : -
-
- {$orderReturnInfo['id_transaction']|escape:'html':'UTF-8'} -
-
-
-
- {l s='Refunded amount' mod='hotelreservationsystem'} : + {l s='Refunded amount:' mod='hotelreservationsystem'}
{displayPrice price=$orderReturnInfo['refunded_amount'] currency=$orderInfo['id_currency']}
+ + {if $orderReturnInfo['payment_mode'] != '' && $orderReturnInfo['id_transaction'] != ''} +
+
+ {l s='Payment mode:' mod='hotelreservationsystem'} +
+
+ {$orderReturnInfo['payment_mode']|escape:'html':'UTF-8'} +
+
+
+
+ {l s='Transaction ID:' mod='hotelreservationsystem'} +
+
+ {$orderReturnInfo['id_transaction']|escape:'html':'UTF-8'} +
+
+ {/if} + + {if isset($orderReturnInfo['return_type'])} + {if $orderReturnInfo['return_type'] == OrderReturn::RETURN_TYPE_CART_RULE} +
+
+ {l s='Voucher ID:' mod='hotelreservationsystem'} +
+ +
+ {elseif $orderReturnInfo['return_type'] == OrderReturn::RETURN_TYPE_ORDER_SLIP} +
+
+ {l s='Credit Slip ID:' mod='hotelreservationsystem'} +
+
+ #{$orderReturnInfo['id_return_type']} + + + {l s='Download' mod='hotelreservationsystem'} + +
+
+ {/if} + {/if} {/if} {else}
@@ -207,7 +236,7 @@
diff --git a/themes/hotel-reservation-theme/order-slip.tpl b/themes/hotel-reservation-theme/order-slip.tpl index 931d3e133..846b25e84 100644 --- a/themes/hotel-reservation-theme/order-slip.tpl +++ b/themes/hotel-reservation-theme/order-slip.tpl @@ -31,6 +31,15 @@

{l s='Credit slips you have received after canceled orders'}.

+ +{include file="$tpl_dir./errors.tpl"} + +{if isset($smarty.get.confirmation) && $smarty.get.confirmation} +

+ {l s='Your voucher has been generated successfully and sent via email.'} {'Click here'} {' to see your all vouchers.'} +

+{/if} +
{if $ordersSlip && count($ordersSlip)}
@@ -39,7 +48,9 @@ - + + + @@ -47,22 +58,40 @@ + + {/foreach}
{l s='Credit slip'} {l s='Order'} {l s='Date issued'}{l s='View credit slip'}{l s='View credit slip'}{l s='Status'}{l s='Actions'}
- {l s='#%s' sprintf=$slip.id_order_slip|string_format:"%06d"} + #{Configuration::get('PS_CREDIT_SLIP_PREFIX', $lang_id)}{$slip.id_order_slip|string_format:"%06d"} - {l s='#%s' sprintf=$slip.id_order|string_format:"%06d"} + #{$slip.id_order|string_format:"%06d"} {dateFormat date=$slip.date_add full=0} - + {l s='PDF'} + {if $slip.redeem_status == OrderSlip::REDEEM_STATUS_REDEEMED} + {l s='Redeemed'} + {else} + {l s='Active'} + {/if} + + {if $slip.redeem_status == OrderSlip::REDEEM_STATUS_ACTIVE && !$slip.id_cart_rule} + + {l s='Generate Voucher'} + + {elseif $slip.redeem_status == OrderSlip::REDEEM_STATUS_REDEEMED && $slip.id_cart_rule} + {l s='Voucher Generated'} + {elseif $slip.redeem_status == OrderSlip::REDEEM_STATUS_REDEEMED && !$slip.id_cart_rule} + -- + {/if} +