diff --git a/admin/themes/default/sass/controllers/_customer-thread.sass b/admin/themes/default/sass/controllers/_customer-thread.sass index a3678333d..a0b8e1d65 100644 --- a/admin/themes/default/sass/controllers/_customer-thread.sass +++ b/admin/themes/default/sass/controllers/_customer-thread.sass @@ -48,7 +48,22 @@ @include left(1px) @include box-shadow(white 0 0 0 3px inset) +.submitReply + i[class^="icon-"] + display: block + width: 30px + height: 30px + margin: 0 auto + font-size: 28px + background: transparent + background-size: 26px + background-position: center +.table.customer_thread, #MeaningStatus + .text-success + color: #56CE56 + .text-warning + color: #FCC94F .message-item-initial h2 diff --git a/admin/themes/default/sass/controllers/_order.sass b/admin/themes/default/sass/controllers/_order.sass index 2cce1d798..18d934810 100644 --- a/admin/themes/default/sass/controllers/_order.sass +++ b/admin/themes/default/sass/controllers/_order.sass @@ -84,6 +84,11 @@ .panel-refund-request .refunded_amount margin-top: 2px +.order-notes + .panel-content + max-height: 240px + overflow: auto + .panel-guest_address .panel-heading align-items: center diff --git a/admin/themes/default/template/controllers/customer_threads/helpers/list/list_header.tpl b/admin/themes/default/template/controllers/customer_threads/helpers/list/list_header.tpl index eb5a77d3c..4b0ded7a7 100644 --- a/admin/themes/default/template/controllers/customer_threads/helpers/list/list_header.tpl +++ b/admin/themes/default/template/controllers/customer_threads/helpers/list/list_header.tpl @@ -51,7 +51,7 @@ {l s='No new messages'} {else} - {$total_thread} + {$total_thread} {if $total_thread > 1}{l s='New messages'}{else}{l s='New message'}{/if} {/if} @@ -64,10 +64,10 @@ {l s='Meaning of status'} @@ -78,12 +78,12 @@ -{/block} \ No newline at end of file +{/block} diff --git a/admin/themes/default/template/controllers/customer_threads/helpers/view/message.tpl b/admin/themes/default/template/controllers/customer_threads/helpers/view/message.tpl index d006ce679..77b4f2d8e 100644 --- a/admin/themes/default/template/controllers/customer_threads/helpers/view/message.tpl +++ b/admin/themes/default/template/controllers/customer_threads/helpers/view/message.tpl @@ -45,14 +45,15 @@ {if !$initial}

- {if $type == 'customer'} - {$message.customer_name|escape:'html':'UTF-8'} - {else} - {$message.employee_name|escape:'html':'UTF-8'} - {/if} + {if $type == 'customer'} + {$message.customer_name|escape:'html':'UTF-8'} + {else} + {$message.employee_name|escape:'html':'UTF-8'} + {/if}

{/if}   - {dateFormat date=$message.date_add full=0} - {$message.date_add|substr:11:5} + {if $message.private}{l s='Private'}{/if} {if isset($message.file_name)}   {l s="Attachment"}{/if} {if isset($message.product_name)}   {l s="Room type:"} {$message.product_name|escape:'html':'UTF-8'} {/if}

{$message.message|escape:'html':'UTF-8'|nl2br}

diff --git a/admin/themes/default/template/controllers/customer_threads/helpers/view/view.tpl b/admin/themes/default/template/controllers/customer_threads/helpers/view/view.tpl index 2d4a2409f..fb68b64e7 100644 --- a/admin/themes/default/template/controllers/customer_threads/helpers/view/view.tpl +++ b/admin/themes/default/template/controllers/customer_threads/helpers/view/view.tpl @@ -30,11 +30,6 @@
{l s="Thread"}: #{$id_customer_thread|intval} - {if isset($next_thread) && $next_thread} - - {$next_thread.name} - - {/if}
@@ -116,7 +111,9 @@ {l s="Choose a template"} --> - + + +
@@ -180,5 +177,3 @@ {/block} - - diff --git a/admin/themes/default/template/controllers/orders/form.tpl b/admin/themes/default/template/controllers/orders/form.tpl index 105e6b608..4574f7277 100644 --- a/admin/themes/default/template/controllers/orders/form.tpl +++ b/admin/themes/default/template/controllers/orders/form.tpl @@ -282,6 +282,10 @@ }) $('#order_message').live('change', function(e) { e.preventDefault(); + let visibility = 0; + if ($('#visibility').prop('checked')) { + visibility = 1; + } $.ajax({ type:"POST", url: "{$link->getAdminLink('AdminCarts')|addslashes}", @@ -294,8 +298,9 @@ action: "updateOrderMessage", id_cart: id_cart, id_customer: id_customer, - message: $(this).val() - }, + message: $(this).val(), + visibility: visibility + }, success : function(res) { displaySummary(res); @@ -2170,6 +2175,15 @@ +
+ +

+ +

+
{if !$PS_CATALOG_MODE}
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 2f5c37c16..b823f98a1 100644 --- a/admin/themes/default/template/controllers/orders/helpers/view/view.tpl +++ b/admin/themes/default/template/controllers/orders/helpers/view/view.tpl @@ -704,7 +704,7 @@ {* Order Internal notes *} {if (sizeof($messages))} -
+
 {l s='Order Notes'}
@@ -1153,7 +1153,11 @@
 {l s='Messages'} {sizeof($customer_thread_message)} - {l s='Show all messages'} + {if $id_customer_thread} + {l s='Show all messages'} + {else} + {l s='Show all messages'} + {/if}
{if $can_edit} diff --git a/classes/CustomerMessage.php b/classes/CustomerMessage.php index a4b6c920d..6ac21bbef 100644 --- a/classes/CustomerMessage.php +++ b/classes/CustomerMessage.php @@ -32,6 +32,7 @@ class CustomerMessageCore extends ObjectModel public $message; public $file_name; public $ip_address; + public $id_product; public $user_agent; public $private; public $date_add; @@ -51,6 +52,7 @@ class CustomerMessageCore extends ObjectModel 'id_employee' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'id_customer_thread' => array('type' => self::TYPE_INT), 'ip_address' => array('type' => self::TYPE_STRING, 'validate' => 'isIp2Long', 'size' => 15), + 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'message' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml', 'required' => true, 'size' => 16777216), 'file_name' => array('type' => self::TYPE_STRING), 'user_agent' => array('type' => self::TYPE_STRING), @@ -72,7 +74,7 @@ class CustomerMessageCore extends ObjectModel ), ); - public static function getMessagesByOrderId($id_order, $private = true) + public static function getMessagesByOrderId($id_order, $private = true, $limit = false) { return Db::getInstance()->executeS(' SELECT cm.*, @@ -91,8 +93,9 @@ class CustomerMessageCore extends ObjectModel WHERE ct.id_order = '.(int)$id_order.' '.(!$private ? 'AND cm.`private` = 0' : '').' GROUP BY cm.id_customer_message - ORDER BY cm.date_add DESC - '); + ORDER BY cm.date_add DESC'. + (($limit) ? ' LIMIT '.(int) $limit: ' ') + ); } public static function getTotalCustomerMessages($where = null) diff --git a/classes/CustomerThread.php b/classes/CustomerThread.php index 7e1b721af..367499a0a 100644 --- a/classes/CustomerThread.php +++ b/classes/CustomerThread.php @@ -32,13 +32,20 @@ class CustomerThreadCore extends ObjectModel public $id_contact; public $id_customer; public $id_order; - public $id_product; + public $user_name; + public $phone; + public $subject; public $status; public $email; public $token; public $date_add; public $date_upd; + const QLO_CUSTOMER_THREAD_STATUS_OPEN = 1; + const QLO_CUSTOMER_THREAD_STATUS_PENDING1 = 2; + const QLO_CUSTOMER_THREAD_STATUS_PENDING2 = 3; + const QLO_CUSTOMER_THREAD_STATUS_CLOSED = 4; + /** * @see ObjectModel::$definition */ @@ -48,10 +55,12 @@ class CustomerThreadCore extends ObjectModel 'fields' => array( 'id_lang' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), 'id_contact' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId', 'required' => true), + 'user_name' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'), + 'phone' => array('type' => self::TYPE_STRING, 'validate' => 'isPhoneNumber', 'size' => 32), + 'subject' => array('type' => self::TYPE_STRING, 'validate' => 'isCleanHtml'), 'id_shop' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'id_customer' =>array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), - 'id_product' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedId'), 'email' => array('type' => self::TYPE_STRING, 'validate' => 'isEmail', 'size' => 254), 'token' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName', 'required' => true), 'status' => array('type' => self::TYPE_STRING), @@ -158,15 +167,38 @@ class CustomerThreadCore extends ObjectModel return Db::getInstance()->executeS($sql); } - public static function getIdCustomerThreadByEmailAndIdOrder($email, $id_order, $id_contact = false) + public static function getIdCustomerThreadByEmailAndIdOrder($email, $id_order, $id_contact = false, $query = false) + { + return Db::getInstance()->getValue(' + SELECT a.`id_customer_thread` + FROM `'._DB_PREFIX_.'customer_thread` a + WHERE a.`email` = \''.pSQL($email).'\' + AND a.`id_shop` = '.(int)Context::getContext()->shop->id.' + AND a.`id_order` = '.(int)$id_order.' '. + (($id_contact) ? ' AND a.`id_contact`='.(int) $id_contact : ' '). + (($query) ? $query : ' ') + ); + } + + + public static function getIdCustomerThreadByIdOrder($idOrder) { return Db::getInstance()->getValue(' SELECT cm.id_customer_thread FROM '._DB_PREFIX_.'customer_thread cm - WHERE cm.email = \''.pSQL($email).'\' - AND cm.id_shop = '.(int)Context::getContext()->shop->id.' - AND cm.id_order = '.(int)$id_order.' '. - (($id_contact) ? ' AND cm.id_contact='.(int) $id_contact : ' ') + WHERE cm.id_shop = '.(int)Context::getContext()->shop->id.' + AND cm.id_order = '.(int)$idOrder + ); + } + + + public static function getIdCustomerThreadByToken($token) + { + return Db::getInstance()->getValue(' + SELECT cm.id_customer_thread + FROM '._DB_PREFIX_.'customer_thread cm + WHERE cm.id_shop = '.(int)Context::getContext()->shop->id.' + AND token = \''.pSQL($token).'\'' ); } @@ -234,7 +266,7 @@ class CustomerThreadCore extends ObjectModel return Db::getInstance()->getValue(' SELECT id_customer_thread FROM '._DB_PREFIX_.'customer_thread ct - WHERE ct.status = "open" + WHERE ct.status = '.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN.' AND ct.date_upd = ( SELECT date_add FROM '._DB_PREFIX_.'customer_message WHERE (id_employee IS NULL OR id_employee = 0) diff --git a/classes/PaymentModule.php b/classes/PaymentModule.php index 516a755ab..0dd260fa1 100644 --- a/classes/PaymentModule.php +++ b/classes/PaymentModule.php @@ -699,7 +699,7 @@ abstract class PaymentModuleCore extends Module $customer_thread->id_order = (int)$order->id; $customer_thread->id_lang = (int)$this->context->language->id; $customer_thread->email = $this->context->customer->email; - $customer_thread->status = 'open'; + $customer_thread->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $customer_thread->token = Tools::passwdGen(12); $customer_thread->add(); @@ -707,7 +707,7 @@ abstract class PaymentModuleCore extends Module $customer_message->id_customer_thread = $customer_thread->id; $customer_message->id_employee = 0; $customer_message->message = $update_message->message; - $customer_message->private = 0; + $customer_message->private = !Tools::getValue('visibility'); if (!$customer_message->add()) { $this->errors[] = Tools::displayError('An error occurred while saving message'); diff --git a/controllers/admin/AdminCartsController.php b/controllers/admin/AdminCartsController.php index 2ce84593f..e4179e2fa 100644 --- a/controllers/admin/AdminCartsController.php +++ b/controllers/admin/AdminCartsController.php @@ -587,6 +587,7 @@ class AdminCartsControllerCore extends AdminController $message->message = $message_content; $message->id_cart = (int)$this->context->cart->id; $message->id_customer = (int)$this->context->cart->id_customer; + $message->private = !Tools::getValue('visibility'); $message->save(); } } elseif (Validate::isLoadedObject($message)) { @@ -598,7 +599,7 @@ class AdminCartsControllerCore extends AdminController public function ajaxProcessUpdateCurrency() { - if ($this->tabAccess['edit'] === '1') { + if ($this->tabAccess['edit'] === '1' || $this->tabAccess['add'] === '1') { $currency = new Currency((int)Tools::getValue('id_currency')); if (Validate::isLoadedObject($currency) && !$currency->deleted && $currency->active) { $this->context->cart->id_currency = (int)$currency->id; diff --git a/controllers/admin/AdminCustomerThreadsController.php b/controllers/admin/AdminCustomerThreadsController.php index 2d7b52891..0916fb3eb 100644 --- a/controllers/admin/AdminCustomerThreadsController.php +++ b/controllers/admin/AdminCustomerThreadsController.php @@ -51,10 +51,22 @@ class AdminCustomerThreadsControllerCore extends AdminController } $icon_array = array( - 'open' => array('class' => 'icon-circle text-success', 'alt' => $this->l('Open')), - 'closed' => array('class' => 'icon-circle text-danger', 'alt' => $this->l('Closed')), - 'pending1' => array('class' => 'icon-circle text-warning', 'alt' => $this->l('Pending 1')), - 'pending2' => array('class' => 'icon-circle text-warning', 'alt' => $this->l('Pending 2')), + CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN => array( + 'class' => 'icon-circle text-success', + 'alt' => $this->l('Open') + ), + CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED => array( + 'class' => 'icon-circle text-danger', + 'alt' => $this->l('Closed') + ), + CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1 => array( + 'class' => 'icon-circle text-warning', + 'alt' => $this->l('Pending 1') + ), + CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2 => array( + 'class' => 'icon-circle text-warning', + 'alt' => $this->l('Pending 2') + ), ); $status_array = array(); @@ -67,7 +79,9 @@ class AdminCustomerThreadsControllerCore extends AdminController $this->access_join = ' LEFT JOIN '._DB_PREFIX_.'orders ord ON (a.id_order = ord.id_order)'; $this->access_join .= ' LEFT JOIN '._DB_PREFIX_.'htl_booking_detail hbd ON (hbd.id_order = ord.id_order)'; if ($acsHtls = HotelBranchInformation::getProfileAccessedHotels($this->context->employee->id_profile, 1, 1)) { - $this->access_where = ' AND IF(a.`id_order`, hbd.`id_hotel` IN ('.implode(',', $acsHtls).'), 1)'; + $this->access_where = ' WHERE IF(a.`id_order`, hbd.`id_hotel` IN ('.implode(',', $acsHtls).'), 1)'; + } else { + $this->access_where = ' WHERE a.`id_order` = 0'; } $this->fields_list = array( @@ -79,12 +93,19 @@ class AdminCustomerThreadsControllerCore extends AdminController 'customer' => array( 'title' => $this->l('Customer'), 'filter_key' => 'customer', + 'callback' => 'getCustomerLink', 'tmpTableFilter' => true, ), 'email' => array( 'title' => $this->l('Email'), 'filter_key' => 'a!email', ), + 'phone' => array( + 'title' => $this->l('Phone'), + 'filter_key' => 'a!phone', + 'optional' => true, + 'visible_default' => true, + ), 'contact' => array( 'title' => $this->l('Type'), 'type' => 'select', @@ -92,12 +113,21 @@ class AdminCustomerThreadsControllerCore extends AdminController 'filter_key' => 'cl!id_contact', 'filter_type' => 'int', ), + 'subject' => array( + 'title' => $this->l('Subject'), + 'filter_key' => 'a!subject', + 'tmpTableFilter' => true, + 'maxlength' => 40, + 'optional' => true, + 'visible_default' => true, + ), 'language' => array( 'title' => $this->l('Language'), 'type' => 'select', 'list' => $language_array, 'filter_key' => 'l!id_lang', 'filter_type' => 'int', + 'optional' => true, ), 'status' => array( 'title' => $this->l('Status'), @@ -118,9 +148,10 @@ class AdminCustomerThreadsControllerCore extends AdminController 'filter_key' => 'messages', 'tmpTableFilter' => true, 'maxlength' => 40, + 'optional' => true, ), 'private' => array( - 'title' => $this->l('Private'), + 'title' => $this->l('Has Private'), 'type' => 'select', 'filter_key' => 'private', 'align' => 'center', @@ -135,6 +166,7 @@ class AdminCustomerThreadsControllerCore extends AdminController 'title' => $this->l('Last message'), 'havingFilter' => true, 'type' => 'datetime', + 'optional' => true, ), ); @@ -147,22 +179,61 @@ class AdminCustomerThreadsControllerCore extends AdminController ); $this->shopLinkType = 'shop'; + $arr = array(); + if ($contacts = Contact::getContacts($this->context->language->id)) { + foreach ($contacts as $contact) { + $arr[] = array('email_message' => $contact['id_contact'], 'name' => $contact['name']); + } + } $this->fields_options = array( 'contact' => array( 'title' => $this->l('Contact options'), 'fields' => array( 'PS_CUSTOMER_SERVICE_FILE_UPLOAD' => array( - 'title' => $this->l('Allow file uploading'), - 'hint' => $this->l('Allow customers to upload files using the contact page.'), - 'type' => 'bool' - ), + 'title' => $this->l('Allow file uploading'), + 'hint' => $this->l('Allow customers to upload files using the contact page.'), + 'type' => 'bool' + ), + 'PS_MAIL_EMAIL_MESSAGE' => array( + 'title' => $this->l('Send email to'), + 'desc' => $this->l('Where customers send messages from the order page.'), + 'validation' => 'isUnsignedId', + 'type' => 'select', + 'cast' => 'intval', + 'identifier' => 'email_message', + 'list' => $arr + ), + 'PS_CUSTOMER_SERVICE_CONTACT_ALLOW' => array( + 'title' => $this->l('Allow guest to select contact'), + 'hint' => $this->l('Allow guest to select the contact while submitting message from the contact page.'), + 'type' => 'bool' + ), + 'PS_CUSTOMER_SERVICE_EMAIL_MESSAGE' => array( + 'title' => $this->l('Send email to'), + 'desc' => $this->l('Where customers send messages from the Contact page.'), + 'validation' => 'isUnsignedId', + 'type' => 'select', + 'cast' => 'intval', + 'identifier' => 'email_message', + 'list' => $arr + ), + 'PS_CUSTOMER_SERVICE_NAME_REQUIRED' => array( + 'title' => $this->l('Set Name as required'), + 'hint' => $this->l('Set Name as required while submitting message from the contact page.'), + 'type' => 'bool' + ), + 'PS_CUSTOMER_SERVICE_PHONE_REQUIRED' => array( + 'title' => $this->l('Set Phone as required'), + 'hint' => $this->l('Set Phone as required while submitting message from the contact page.'), + 'type' => 'bool' + ), 'PS_CUSTOMER_SERVICE_SIGNATURE' => array( - 'title' => $this->l('Default message'), - 'hint' => $this->l('Please fill out the message fields that appear by default when you answer a thread on the customer service page.'), - 'type' => 'textareaLang', - 'lang' => true - ) + 'title' => $this->l('Default message'), + 'hint' => $this->l('Please fill out the message fields that appear by default when you answer a thread on the customer service page.'), + 'type' => 'textareaLang', + 'lang' => true + ) ), 'submit' => array( 'title' => $this->l('Save'), @@ -242,6 +313,25 @@ class AdminCustomerThreadsControllerCore extends AdminController ); parent::__construct(); + $this->_new_list_header_design = true; + $this->list_no_link = true; + } + + public function getCustomerLink($customer, $tr) + { + if ($tr['id_customer']) { + return ''.$customer.' (#'.$tr['id_customer'].')'; + } + + return $customer; + } + + public function setMedia() + { + parent::setMedia(); + if (!$this->display || $this->display == 'list') { + $this->addJS(_PS_JS_DIR_.'admin/customer_thread.js'); + } } public function renderList() @@ -253,7 +343,7 @@ class AdminCustomerThreadsControllerCore extends AdminController $this->addRowAction('delete'); $this->_select = ' - CONCAT(c.`firstname`," ",c.`lastname`) as customer, cl.`name` as contact, l.`name` as language, group_concat(message) as messages, cm.private, + IF(a.`user_name`="", CONCAT(c.`firstname`," ",c.`lastname`), a.`user_name`) AS customer, cl.`name` as contact, l.`name` as language, group_concat(message) as messages, cm.private, ( SELECT IFNULL(CONCAT(LEFT(e.`firstname`, 1),". ",e.`lastname`), "--") FROM `'._DB_PREFIX_.'customer_message` cm2 @@ -274,10 +364,6 @@ class AdminCustomerThreadsControllerCore extends AdminController LEFT JOIN `'._DB_PREFIX_.'contact_lang` cl ON (cl.`id_contact` = a.`id_contact` AND cl.`id_lang` = '.(int)$this->context->language->id.')'; - if ($id_order = Tools::getValue('id_order')) { - $this->_where .= ' AND id_order = '.(int)$id_order; - } - $this->_group = 'GROUP BY cm.id_customer_thread'; $this->_orderBy = 'id_customer_thread'; $this->_orderWay = 'DESC'; @@ -286,19 +372,42 @@ class AdminCustomerThreadsControllerCore extends AdminController $categories = Contact::getCategoriesContacts(); - $params = array( - $this->l('Total threads') => $all = CustomerThread::getTotalCustomerThreads(), - $this->l('Threads pending') => $pending = CustomerThread::getTotalCustomerThreads('status LIKE "%pending%"'), - $this->l('Total number of customer messages') => CustomerMessage::getTotalCustomerMessages('id_employee = 0'), - $this->l('Total number of employee messages') => CustomerMessage::getTotalCustomerMessages('id_employee != 0'), - $this->l('Unread threads') => $unread = CustomerThread::getTotalCustomerThreads('status = "open"'), - $this->l('Closed threads') => $all - ($unread + $pending) + $stats = array( + array( + 'title' => $this->l('Total threads'), + 'val' => $all = CustomerThread::getTotalCustomerThreads(), + ), + array( + 'title' => $this->l('Threads pending'), + 'val' => $pending = CustomerThread::getTotalCustomerThreads( + 'status='.(int) CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1.' + OR status='.(int) CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2 + ), + ), + array( + 'title' => $this->l('Total number of customer messages'), + 'val' => CustomerMessage::getTotalCustomerMessages('id_employee = 0'), + ), + array( + 'title' => $this->l('Total number of employee messages'), + 'val' => CustomerMessage::getTotalCustomerMessages('id_employee != 0'), + ), + array( + 'title' => $this->l('Unread threads'), + 'val' => $unread = CustomerThread::getTotalCustomerThreads( + 'status='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN + ), + ), + array( + 'title' => $this->l('Closed threads'), + 'val' => $all - ($unread + $pending), + ), ); $this->tpl_list_vars = array( 'contacts' => $contacts, 'categories' => $categories, - 'params' => $params + 'stats' => $stats ); return parent::renderList(); @@ -342,10 +451,9 @@ class AdminCustomerThreadsControllerCore extends AdminController ); } if ($id_status = (int)Tools::getValue('setstatus')) { - $status_array = array(1 => 'open', 2 => 'closed', 3 => 'pending1', 4 => 'pending2'); Db::getInstance()->execute(' UPDATE '._DB_PREFIX_.'customer_thread - SET status = "'.$status_array[$id_status].'" + SET status = "'.(int) $id_status.'" WHERE id_customer_thread = '.(int)$id_customer_thread.' LIMIT 1 '); } @@ -363,7 +471,7 @@ class AdminCustomerThreadsControllerCore extends AdminController LEFT OUTER JOIN '._DB_PREFIX_.'customer c ON (c.email = ct.email) WHERE ct.id_customer_thread = '.(int)Tools::getValue('id_customer_thread').' - ORDER BY cm.date_add DESC + ORDER BY cm.date_add, cm.id_employee, cm.private DESC '); $output = $this->displayMessage($messages, true, (int)Tools::getValue('id_employee_forward')); $cm = new CustomerMessage(); @@ -395,7 +503,8 @@ class AdminCustomerThreadsControllerCore extends AdminController $employee->firstname.' '.$employee->lastname, $current_employee->email, $current_employee->firstname.' '.$current_employee->lastname, - null, null, _PS_MAIL_DIR_, true)) { + null, null, _PS_MAIL_DIR_, true) + ) { $cm->id_employee = (int)$employee->id; $cm->private = 1; $cm->message = $this->l('Message forwarded to').' '.$employee->firstname.' '.$employee->lastname."\n".$this->l('Comment:').' '.$message; @@ -424,7 +533,7 @@ class AdminCustomerThreadsControllerCore extends AdminController $this->errors[] = '
'.Tools::displayError('The email address is invalid.').'
'; } } - if (Tools::isSubmit('submitReply')) { + if (Tools::isSubmit('submitReply') || Tools::isSubmit('submitReplyAndClose')) { $ct = new CustomerThread($id_customer_thread); ShopUrl::cacheMainDomainForShop((int)$ct->id_shop); @@ -446,14 +555,26 @@ class AdminCustomerThreadsControllerCore extends AdminController $file_attachment['mime'] = $_FILES['joinFile']['type']; } $customer = new Customer($ct->id_customer); + if ($ct->id_order) { + $link = Tools::url( + $this->context->link->getPageLink('order-detail', true, (int)$ct->id_lang, null, false, $ct->id_shop), + 'id_order='.$ct->id_order + ); + } else { + $link = Tools::url( + $this->context->link->getPageLink('contact', true, (int)$ct->id_lang, null, false, $ct->id_shop), + 'token='.$ct->token + ); + } + + $headingText = $this->l('Hi'); + if ($customer->id) { + $headingText .= ' '.$customer->firstname.' '.$customer->lastname; + } $params = array( '{reply}' => Tools::nl2br(Tools::getValue('reply_message')), - '{link}' => Tools::url( - $this->context->link->getPageLink('contact', true, (int)$ct->id_lang, null, false, $ct->id_shop), - 'id_customer_thread='.(int)$ct->id.'&token='.$ct->token - ), - '{firstname}' => $customer->firstname, - '{lastname}' => $customer->lastname + '{link}' => $link, + '{headingtext}' => $headingText ); //#ct == id_customer_thread #tc == token of thread <== used in the synchronization imap $contact = new Contact((int)$ct->id_contact, (int)$ct->id_lang); @@ -471,8 +592,12 @@ class AdminCustomerThreadsControllerCore extends AdminController 'reply_msg', sprintf(Mail::l('An answer to your message is available #ct%1$s #tc%2$s', $ct->id_lang), $ct->id, $ct->token), $params, Tools::getValue('msg_email'), null, $from_email, $from_name, $file_attachment, null, - _PS_MAIL_DIR_, true, $ct->id_shop)) { - $ct->status = 'closed'; + _PS_MAIL_DIR_, true, $ct->id_shop) + ) { + if (Tools::isSubmit('submitReplyAndClose')) { + $ct->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED; + } + $ct->update(); } Tools::redirectAdmin( @@ -481,7 +606,24 @@ class AdminCustomerThreadsControllerCore extends AdminController } else { $this->errors[] = Tools::displayError('An error occurred. Your message was not sent. Please contact your system administrator.'); } + } else if (Tools::isSubmit('submitReplyAsPrivate')) { + $ct = new CustomerThread($id_customer_thread); + ShopUrl::cacheMainDomainForShop((int)$ct->id_shop); + $cm = new CustomerMessage(); + $cm->id_employee = (int)$this->context->employee->id; + $cm->id_customer_thread = $ct->id; + $cm->ip_address = (int)ip2long(Tools::getRemoteAddr()); + $cm->message = Tools::getValue('reply_message'); + $cm->private = 1; + $cm->read = 1; + if (($error = $cm->validateField('message', $cm->message, null, array(), true)) !== true) { + $this->errors[] = $error; + } elseif (!$cm->add()) { + $this->errors[] = Tools::displayError('Some error occured while saving the message'); + } } + + } return parent::postProcess(); @@ -603,64 +745,54 @@ class AdminCustomerThreadsControllerCore extends AdminController } } - $next_thread = CustomerThread::getNextThread((int)$thread->id); - $contacts = Contact::getContacts($this->context->language->id); - $actions = array(); - if ($next_thread) { - $next_thread = array( - 'href' => self::$currentIndex.'&id_customer_thread='.(int)$next_thread.'&viewcustomer_thread&token='.$this->token, - 'name' => $this->l('Reply to the next unanswered message in this thread') - ); - } - - if ($thread->status != 'closed') { - $actions['closed'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=2&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + if ($thread->status != CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED) { + $actions[CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED.'&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Mark as "handled"'), 'name' => 'setstatus', - 'value' => 2 + 'value' => CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED ); } else { - $actions['open'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + $actions[CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN.'&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Re-open'), 'name' => 'setstatus', - 'value' => 1 + 'value' => CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN ); } - if ($thread->status != 'pending1') { - $actions['pending1'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=3&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + if ($thread->status != CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1) { + $actions[CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1.'&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Mark as "pending 1" (will be answered later)'), 'name' => 'setstatus', - 'value' => 3 + 'value' => CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1 ); } else { - $actions['pending1'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + $actions[CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING1] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN.'&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Disable pending status'), 'name' => 'setstatus', - 'value' => 1 + 'value' => CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN ); } - if ($thread->status != 'pending2') { - $actions['pending2'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=4&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + if ($thread->status != CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2) { + $actions[CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2.'&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Mark as "pending 2" (will be answered later)'), 'name' => 'setstatus', - 'value' => 4 + 'value' => CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2 ); } else { - $actions['pending2'] = array( - 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus=1&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, + $actions[CustomerThread::QLO_CUSTOMER_THREAD_STATUS_PENDING2] = array( + 'href' => self::$currentIndex.'&viewcustomer_thread&setstatus='.CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN.'&id_customer_thread='.(int)Tools::getValue('id_customer_thread').'&viewmsg&token='.$this->token, 'label' => $this->l('Disable pending status'), 'name' => 'setstatus', - 'value' => 1 + 'value' => CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN ); } @@ -710,7 +842,6 @@ class AdminCustomerThreadsControllerCore extends AdminController 'messages' => $messages, 'first_message' => $first_message, 'contact' => $contact, - 'next_thread' => $next_thread, 'orders' => isset($orders) ? $orders : false, 'customer' => isset($customer) ? $customer : false, 'products' => isset($products) ? $products : false, @@ -721,10 +852,6 @@ class AdminCustomerThreadsControllerCore extends AdminController 'timeline_items' => $timeline_items, ); - if ($next_thread) { - $this->tpl_view_vars['next_thread'] = $next_thread; - } - return parent::renderView(); } @@ -737,10 +864,15 @@ class AdminCustomerThreadsControllerCore extends AdminController $content = ''; if (!$message['private']) { - $content .= $this->l('Message to: ').' '.(!$message['id_employee'] ? $message['subject'] : $message['customer_name']).'
'; + if ($message['id_employee']) { + $content .= $this->l('Message to: ').' '.($message['customer_name']).'

'; + } + } else { + $content .= ''.$this->l('Private').'

'; } + if (Validate::isLoadedObject($product)) { - $content .= '
'.$this->l('Room type: ').''.$product->name.'

'; + $content .= $this->l('Room type: ').''.$product->name.'

'; } $content .= Tools::safeOutput($message['message']); @@ -1079,7 +1211,7 @@ class AdminCustomerThreadsControllerCore extends AdminController $ct->id_contact = $id_contact; $ct->id_lang = (int)Configuration::get('PS_LANG_DEFAULT'); $ct->id_shop = $this->context->shop->id; //new customer threads for unrecognized mails are not shown without shop id - $ct->status = 'open'; + $ct->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $ct->token = Tools::passwdGen(12); $ct->add(); } else { diff --git a/controllers/admin/AdminEmailsController.php b/controllers/admin/AdminEmailsController.php index b933780ad..47159695d 100644 --- a/controllers/admin/AdminEmailsController.php +++ b/controllers/admin/AdminEmailsController.php @@ -80,25 +80,11 @@ class AdminEmailsControllerCore extends AdminController } parent::__construct(); - - foreach (Contact::getContacts($this->context->language->id) as $contact) { - $arr[] = array('email_message' => $contact['id_contact'], 'name' => $contact['name']); - } - $this->fields_options = array( 'email' => array( 'title' => $this->l('Email'), 'icon' => 'icon-envelope', - 'fields' => array( - 'PS_MAIL_EMAIL_MESSAGE' => array( - 'title' => $this->l('Send email to'), - 'desc' => $this->l('Where customers send messages from the order page.'), - 'validation' => 'isUnsignedId', - 'type' => 'select', - 'cast' => 'intval', - 'identifier' => 'email_message', - 'list' => $arr - ), + 'fields' => array( 'PS_MAIL_METHOD' => array( 'title' => '', 'validation' => 'isGenericName', diff --git a/controllers/admin/AdminOrdersController.php b/controllers/admin/AdminOrdersController.php index b852574d7..9c33b112a 100644 --- a/controllers/admin/AdminOrdersController.php +++ b/controllers/admin/AdminOrdersController.php @@ -1424,7 +1424,7 @@ class AdminOrdersControllerCore extends AdminController $customer_thread->id_order = (int)$order->id; $customer_thread->id_lang = (int)$this->context->language->id; $customer_thread->email = $customer->email; - $customer_thread->status = 'open'; + $customer_thread->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $customer_thread->token = Tools::passwdGen(12); $customer_thread->add(); } else { @@ -3036,6 +3036,13 @@ class AdminOrdersControllerCore extends AdminController } } } + + $objCustomerThread = new CustomerThread(); + $messages = Message::getMessagesByOrderId($order->id, true); + if ($customerMessages = CustomerMessage::getMessagesByOrderId($order->id, true)) { + $messages = array_merge($messages, $customerMessages); + } + $this->tpl_view_vars = array( 'guestFormattedAddress' => $guestFormattedAddress, 'idOrderAddressInvoice' => $idOrderAddressInvoice, @@ -3080,8 +3087,9 @@ class AdminOrdersControllerCore extends AdminController 'discounts' => $order->getCartRules(), 'total_paid' => $order->getTotalPaid(), 'customer_thread_message' => CustomerThread::getCustomerMessages($order->id_customer, null, $order->id), + 'id_customer_thread' => $objCustomerThread->getIdCustomerThreadByIdOrder($order->id), 'orderMessages' => OrderMessage::getOrderMessages($order->id_lang), - 'messages' => Message::getMessagesByOrderId($order->id, true), + 'messages' => $messages, 'carrier' => new Carrier($order->id_carrier), 'history' => $history, 'order_payment_detail' => $order_payment_detail, diff --git a/controllers/front/ContactController.php b/controllers/front/ContactController.php index 226909df4..b3b863326 100644 --- a/controllers/front/ContactController.php +++ b/controllers/front/ContactController.php @@ -39,16 +39,40 @@ class ContactControllerCore extends FrontController $saveContactKey = $this->context->cookie->contactFormKey; $extension = array('.txt', '.rtf', '.doc', '.docx', '.pdf', '.zip', '.png', '.jpeg', '.gif', '.jpg'); $file_attachment = Tools::fileAttachment('fileUpload'); - $message = Tools::getValue('message'); // Html entities is not usefull, iscleanHtml check there is no bad html tags. + $message = trim(Tools::getValue('message')); // Html entities is not usefull, iscleanHtml check there is no bad html tags. $url = Tools::getValue('url'); + $phone = Tools::getValue('phone'); + $subject = trim(Tools::getValue('subject')); + $userName = Tools::getValue('user_name'); + $id_contact = (int)Tools::getValue('id_contact'); + $objCustomerThread = new CustomerThread(); + $id_customer_thread = (int)$objCustomerThread->getIdCustomerThreadByToken(Tools::getValue('token')); + $nameRequired = Configuration::get('PS_CUSTOMER_SERVICE_NAME_REQUIRED'); + $phoneRequired = Configuration::get('PS_CUSTOMER_SERVICE_PHONE_REQUIRED'); + if (!Configuration::get('PS_CUSTOMER_SERVICE_CONTACT_ALLOW')) { + $id_contact = (int) Configuration::get('PS_CUSTOMER_SERVICE_EMAIL_MESSAGE'); + } + if (!($from = trim(Tools::getValue('from'))) || !Validate::isEmail($from)) { $this->errors[] = Tools::displayError('Invalid email address.'); } elseif (!$message) { $this->errors[] = Tools::displayError('The message cannot be blank.'); } elseif (!Validate::isCleanHtml($message)) { $this->errors[] = Tools::displayError('Invalid message'); - } elseif (!($id_contact = (int)Tools::getValue('id_contact')) || !(Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id)))) { - $this->errors[] = Tools::displayError('Please select a subject from the list provided. '); + } elseif (!$id_customer_thread && !$subject) { + $this->errors[] = Tools::displayError('The subject cannot be blank.'); + } elseif (!$id_customer_thread && !Validate::isCleanHtml($subject)) { + $this->errors[] = Tools::displayError('Invalid subject$subject'); + } else if (!$id_customer_thread && $nameRequired && !trim($userName)) { + $this->errors[] = Tools::displayError('Name is required.'); + } else if (!$id_customer_thread && trim($nameRequired) && !Validate::isGenericName($userName)) { + $this->errors[] = Tools::displayError('Invalid name.'); + } else if (!$id_customer_thread && $phoneRequired && !trim($phone)) { + $this->errors[] = Tools::displayError('Phone is required.'); + } else if (!$id_customer_thread && trim($phone) && !Validate::isPhoneNumber($phone)) { + $this->errors[] = Tools::displayError('Invalid Phone number.'); + } elseif (!Validate::isLoadedObject($contact = new Contact($id_contact, $this->context->language->id))) { + $this->errors[] = Tools::displayError('Please select a subject from the list provided.'); } elseif (!empty($file_attachment['name']) && $file_attachment['error'] != 0) { $this->errors[] = Tools::displayError('An error occurred during the file-upload process.'); } elseif (!empty($file_attachment['name']) && !in_array(Tools::strtolower(substr($file_attachment['name'], -4)), $extension) && !in_array(Tools::strtolower(substr($file_attachment['name'], -5)), $extension)) { @@ -71,44 +95,15 @@ class ContactControllerCore extends FrontController $id_order = (int) $order->id_customer === (int) $customer->id ? $id_order : 0; } - if (!(( - ($id_customer_thread = (int)Tools::getValue('id_customer_thread')) - && (int)Db::getInstance()->getValue(' - SELECT cm.id_customer_thread FROM '._DB_PREFIX_.'customer_thread cm - WHERE cm.id_customer_thread = '.(int)$id_customer_thread.' AND cm.id_shop = '.(int)$this->context->shop->id.' AND token = \''.pSQL(Tools::getValue('token')).'\'') - ) || ( - $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder($from, $id_order, $id_contact) - ))) { - $fields = Db::getInstance()->executeS(' - SELECT cm.id_customer_thread, cm.id_contact, cm.id_customer, cm.id_order, cm.id_product, cm.email - FROM '._DB_PREFIX_.'customer_thread cm - WHERE email = \''.pSQL($from).'\' AND cm.id_shop = '.(int)$this->context->shop->id.' AND ('. - ($customer->id ? 'id_customer = '.(int)$customer->id.' OR ' : '').' - id_order = '.(int)$id_order.')'); - $score = 0; - foreach ($fields as $key => $row) { - $tmp = 0; - if ((int)$row['id_customer'] && $row['id_customer'] != $customer->id && $row['email'] != $from) { - continue; - } - if ($row['id_order'] != 0 && $id_order != $row['id_order']) { - continue; - } - if ($row['email'] == $from) { - $tmp += 4; - } - if ($row['id_contact'] == $id_contact) { - $tmp++; - } - if (Tools::getValue('id_product') != 0 && $row['id_product'] == Tools::getValue('id_product')) { - $tmp += 2; - } - if ($tmp >= 5 && $tmp >= $score) { - $score = $tmp; - $id_customer_thread = $row['id_customer_thread']; - } - } + if (!$id_customer_thread) { + $id_customer_thread = CustomerThread::getIdCustomerThreadByEmailAndIdOrder( + $from, + $id_order, + $id_contact, + ' AND a.`status` !='. CustomerThread::QLO_CUSTOMER_THREAD_STATUS_CLOSED + ); } + $old_message = Db::getInstance()->getValue(' SELECT cm.message FROM '._DB_PREFIX_.'customer_message cm LEFT JOIN '._DB_PREFIX_.'customer_thread cc on (cm.id_customer_thread = cc.id_customer_thread) @@ -123,13 +118,10 @@ class ContactControllerCore extends FrontController if ($contact->customer_service) { if ((int)$id_customer_thread) { $ct = new CustomerThread($id_customer_thread); - $ct->status = 'open'; + $ct->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $ct->id_lang = (int)$this->context->language->id; $ct->id_contact = (int)$id_contact; $ct->id_order = (int)$id_order; - if ($id_product = (int)Tools::getValue('id_product')) { - $ct->id_product = $id_product; - } $ct->update(); } else { $ct = new CustomerThread(); @@ -137,14 +129,13 @@ class ContactControllerCore extends FrontController $ct->id_customer = (int)$customer->id; } $ct->id_shop = (int)$this->context->shop->id; - $ct->id_order = (int)$id_order; - if ($id_product = (int)Tools::getValue('id_product')) { - $ct->id_product = $id_product; - } + $ct->phone = $phone; + $ct->user_name = $userName; + $ct->subject = $subject; $ct->id_contact = (int)$id_contact; $ct->id_lang = (int)$this->context->language->id; $ct->email = $from; - $ct->status = 'open'; + $ct->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $ct->token = Tools::passwdGen(12); $ct->add(); } @@ -153,6 +144,9 @@ class ContactControllerCore extends FrontController $cm = new CustomerMessage(); $cm->id_customer_thread = $ct->id; $cm->message = $message; + if ($id_product = (int)Tools::getValue('id_product')) { + $cm->id_product = $id_product; + } if (isset($file_attachment['rename']) && !empty($file_attachment['rename']) && rename($file_attachment['tmp_name'], _PS_UPLOAD_DIR_.basename($file_attachment['rename']))) { $cm->file_name = $file_attachment['rename']; @chmod(_PS_UPLOAD_DIR_.basename($file_attachment['rename']), 0664); @@ -266,21 +260,21 @@ class ContactControllerCore extends FrontController 'max_upload_size' => (int)Tools::getMaxUploadSize() )); - if (($id_customer_thread = (int)Tools::getValue('id_customer_thread')) && $token = Tools::getValue('token')) { - $customer_thread = Db::getInstance()->getRow(' + if ($token = Tools::getValue('token')) { + if ($customer_thread = Db::getInstance()->getRow(' SELECT cm.* FROM '._DB_PREFIX_.'customer_thread cm - WHERE cm.id_customer_thread = '.(int)$id_customer_thread.' - AND cm.id_shop = '.(int)$this->context->shop->id.' + WHERE cm.id_shop = '.(int)$this->context->shop->id.' AND token = \''.pSQL($token).'\' - '); - - $order = new Order((int)$customer_thread['id_order']); - if (Validate::isLoadedObject($order)) { - $customer_thread['reference'] = $order->getUniqReference(); + ')) { + $order = new Order((int)$customer_thread['id_order']); + if (Validate::isLoadedObject($order)) { + $customer_thread['reference'] = $order->getUniqReference(); + } + $this->context->smarty->assign('customerThread', $customer_thread); } - $this->context->smarty->assign('customerThread', $customer_thread); } + // Send Hotel location information $gblHtlAddress = Configuration::get('WK_HOTEL_GLOBAL_ADDRESS'); $gblHtlPhone = Configuration::get('WK_HOTEL_GLOBAL_CONTACT_NUMBER'); @@ -320,6 +314,9 @@ class ContactControllerCore extends FrontController 'contacts' => Contact::getContacts($this->context->language->id), 'message' => html_entity_decode(Tools::getValue('message')), 'contactKey' => $contactKey, + 'contactNameRequired' => Configuration::get('PS_CUSTOMER_SERVICE_NAME_REQUIRED'), + 'contactPhoneRequired' => Configuration::get('PS_CUSTOMER_SERVICE_PHONE_REQUIRED'), + 'allowContactSelection' => Configuration::get('PS_CUSTOMER_SERVICE_CONTACT_ALLOW') ) ); diff --git a/controllers/front/OrderDetailController.php b/controllers/front/OrderDetailController.php index 3b15a99b6..892273c29 100644 --- a/controllers/front/OrderDetailController.php +++ b/controllers/front/OrderDetailController.php @@ -695,21 +695,23 @@ class OrderDetailControllerCore extends FrontController $ct->id_contact = 0; $ct->id_customer = (int)$order->id_customer; $ct->id_shop = (int)$this->context->shop->id; - if ($id_product && $order->orderContainProduct($id_product)) { - $ct->id_product = $id_product; - } $ct->id_order = (int)$order->id; $ct->id_lang = (int)$this->context->language->id; $ct->email = $this->context->customer->email; - $ct->status = 'open'; + $ct->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $ct->token = Tools::passwdGen(12); $ct->add(); } else { $ct = new CustomerThread((int)$id_customer_thread); - $ct->status = 'open'; + $ct->status = CustomerThread::QLO_CUSTOMER_THREAD_STATUS_OPEN; $ct->update(); } + if ($id_product && $order->orderContainProduct($id_product)) { + $cm->id_product = $id_product; + } + + $cm->user_agent = $_SERVER['HTTP_USER_AGENT']; $cm->id_customer_thread = $ct->id; $cm->message = $msgText; $cm->ip_address = (int)ip2long($_SERVER['REMOTE_ADDR']); @@ -819,4 +821,4 @@ class OrderDetailControllerCore extends FrontController } } } -} \ No newline at end of file +} diff --git a/install/data/db_structure.sql b/install/data/db_structure.sql index de57c4024..ed8b8c64e 100644 --- a/install/data/db_structure.sql +++ b/install/data/db_structure.sql @@ -633,6 +633,7 @@ CREATE TABLE `PREFIX_customer_message` ( `id_customer_thread` int(11) DEFAULT NULL, `id_employee` int(10) unsigned DEFAULT NULL, `message` MEDIUMTEXT NOT NULL, + `id_product` int(10) unsigned DEFAULT NULL, `file_name` varchar(18) DEFAULT NULL, `ip_address` varchar(16) DEFAULT NULL, `user_agent` varchar(128) DEFAULT NULL, @@ -658,8 +659,10 @@ CREATE TABLE `PREFIX_customer_thread` ( `id_contact` int(10) unsigned NOT NULL, `id_customer` int(10) unsigned DEFAULT NULL, `id_order` int(10) unsigned DEFAULT NULL, - `id_product` int(10) unsigned DEFAULT NULL, - `status` enum('open','closed','pending1','pending2') NOT NULL DEFAULT 'open', + `user_name` VARCHAR(128) DEFAULT NULL, + `phone` VARCHAR(32) DEFAULT NULL, + `subject` TEXT DEFAULT NULL, + `status` INT(10) NOT NULL DEFAULT 1, `email` varchar(128) NOT NULL, `token` varchar(12) DEFAULT NULL, `date_add` datetime NOT NULL, diff --git a/install/data/xml/configuration.xml b/install/data/xml/configuration.xml index 490e2b691..1b6169fc9 100644 --- a/install/data/xml/configuration.xml +++ b/install/data/xml/configuration.xml @@ -946,6 +946,15 @@ 0 + + + 1 + + + 1 + + + 1 diff --git a/js/admin/customer_thread.js b/js/admin/customer_thread.js new file mode 100644 index 000000000..bee35d067 --- /dev/null +++ b/js/admin/customer_thread.js @@ -0,0 +1,32 @@ +/* +* Copyright since 2010 Webkul. +* +* NOTICE OF LICENSE +* +* All right is reserved, +* Please go through this link for complete license : https://store.webkul.com/license.html +* +* 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 https://store.webkul.com/customisation-guidelines/ for more information. +* +* @author Webkul IN +* @copyright Since 2010 Webkul IN +* @license https://store.webkul.com/license.html +*/ + +$(document).ready(function() { + if ($('#PS_CUSTOMER_SERVICE_CONTACT_ALLOW_on').prop('checked')) { + $('[name="PS_CUSTOMER_SERVICE_EMAIL_MESSAGE"]').closest('.form-group').hide(); + } + + $(document).on('change', '[name="PS_CUSTOMER_SERVICE_CONTACT_ALLOW"]', function() { + if ($('#PS_CUSTOMER_SERVICE_CONTACT_ALLOW_on').prop('checked')) { + $('[name="PS_CUSTOMER_SERVICE_EMAIL_MESSAGE"]').closest('.form-group').hide(); + } else { + $('[name="PS_CUSTOMER_SERVICE_EMAIL_MESSAGE"]').closest('.form-group').show(); + } + }); +}); diff --git a/mails/en/reply_msg.html b/mails/en/reply_msg.html index b26a5a41d..c71767da6 100644 --- a/mails/en/reply_msg.html +++ b/mails/en/reply_msg.html @@ -4,51 +4,51 @@ Message from {shop_name} - - - @@ -66,31 +66,29 @@ - - - - Hi {firstname} {lastname}, - - - -   - - - - {reply} - - - -   - - - - - Please do not reply directly to this email, we will not receive it.
- In order to reply, please use the following link: {link}
- - - + + + {headingtext} + + + +   + + + + {reply} + + + +   + + + + + Please do not reply directly to this email, we will not receive it.
+ In order to reply, you can click here
+ +   diff --git a/mails/en/reply_msg.txt b/mails/en/reply_msg.txt index 6c91280e4..c654fa2df 100644 --- a/mails/en/reply_msg.txt +++ b/mails/en/reply_msg.txt @@ -1,14 +1,14 @@ -[/{shop_url}] +[/{shop_url}] -Hi {firstname} {lastname}, +{headingtext}, -{reply} +{reply} -Please do not reply directly to this email, we will not receive it. +Please do not reply directly to this email, we will not receive it. -In order to reply, please use the following link: {link} [/{link}] +In order to reply, you can click here [/{link}]. {shop_name} [/{shop_url}] powered by Webkul(tm) -[https://webkul.com] +[https://webkul.com] diff --git a/themes/hotel-reservation-theme/contact-form.tpl b/themes/hotel-reservation-theme/contact-form.tpl index 6a5aedbe0..144a56043 100644 --- a/themes/hotel-reservation-theme/contact-form.tpl +++ b/themes/hotel-reservation-theme/contact-form.tpl @@ -70,25 +70,56 @@ {/if}
{block name='contact_form_content'} + {if isset($customerThread.token)} + + {else} - {if isset($customerThread.id_contact) && $customerThread.id_contact && $contacts|count} - {assign var=flag value=true} - {foreach from=$contacts item=contact} - {if $contact.id_contact == $customerThread.id_contact} - - - {$flag=false} + {/if} + {if !isset($customerThread.id_contact)} +
+
+ + +
+
+ {/if} +
+
+ + {if isset($customerThread.email)} + + {else} + {/if} - {/foreach} - {if $flag && isset($contacts.0.id_contact)} - - - {/if} - {else} +
+
+ {if !isset($customerThread.id_contact)} +
+
+ + +
+
+
+
+ + +
+
+ {/if} + {if !isset($customerThread.id_contact) && isset($allowContactSelection) && $allowContactSelection}
+ {elseif isset($customerThread.id_contact) && isset($allowContactSelection) && $allowContactSelection} + {/if} -
-
- - {if isset($customerThread.email)} - - {else} - - {/if} -
-
+
+ {l s='* Required fields'} +
{if $fileupload == 1}
diff --git a/themes/hotel-reservation-theme/css/contact-form.css b/themes/hotel-reservation-theme/css/contact-form.css index 5ffae05e0..a53fe0290 100644 --- a/themes/hotel-reservation-theme/css/contact-form.css +++ b/themes/hotel-reservation-theme/css/contact-form.css @@ -200,13 +200,13 @@ font-size: 16px; font-weight: 600; height: 47px; - margin-bottom: 20px; + margin-bottom: 5px; padding: 10px; } .contact_textarea { color: #9a9a9a; height: 150px !important; - margin-bottom: 20px; + margin-bottom: 5px; padding: 10px; font-size: 16px; font-weight: 600; diff --git a/themes/hotel-reservation-theme/css/order-detail.css b/themes/hotel-reservation-theme/css/order-detail.css index 1f188cedc..c3382f5d1 100644 --- a/themes/hotel-reservation-theme/css/order-detail.css +++ b/themes/hotel-reservation-theme/css/order-detail.css @@ -606,7 +606,7 @@ color: #55c65e; } -#sendOrderMessage { +#sendOrderMessage, .select-room-type .card-subheader { margin-bottom: 10px; } @@ -1121,4 +1121,4 @@ text-decoration: underline; text-underline-offset: 3px; } -/* Guest Tracking page styles - end */ \ No newline at end of file +/* Guest Tracking page styles - end */ diff --git a/themes/hotel-reservation-theme/order-detail.tpl b/themes/hotel-reservation-theme/order-detail.tpl index 9ac445d81..f085dceaf 100644 --- a/themes/hotel-reservation-theme/order-detail.tpl +++ b/themes/hotel-reservation-theme/order-detail.tpl @@ -528,6 +528,9 @@
+

+ {l s='To add a comment about a room type, please select one first.'} +