* @copyright 2007-2011 PrestaShop SA * @version Release: $Revision: 7540 $ * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) * International Registered Trademark & Property of PrestaShop SA */ class AdminCustomerThreads extends AdminTab { public function __construct() { global $cookie; $this->table = 'customer_thread'; $this->lang = false; $this->className = 'CustomerThread'; $this->edit = false; $this->view = true; $this->delete = true; $this->_select = 'CONCAT(c.firstname," ",c.lastname) as customer, cl.name as contact, l.name as language, group_concat(message) as messages, ( SELECT IFNULL(CONCAT(LEFT(e.firstname, 1),". ",e.lastname), "--") FROM '._DB_PREFIX_.'customer_message cm2 INNER JOIN '._DB_PREFIX_.'employee e ON e.id_employee = cm2.id_employee WHERE cm2.id_employee > 0 AND cm2.`id_customer_thread` = a.`id_customer_thread` ORDER BY cm2.date_add DESC LIMIT 1) as employee'; $this->_group = 'GROUP BY cm.id_customer_thread'; $this->_join = ' LEFT JOIN `'._DB_PREFIX_.'customer` c ON c.`id_customer` = a.`id_customer` LEFT JOIN `'._DB_PREFIX_.'customer_message` cm ON cm.`id_customer_thread` = a.`id_customer_thread` LEFT JOIN `'._DB_PREFIX_.'lang` l ON l.`id_lang` = a.`id_lang` LEFT JOIN `'._DB_PREFIX_.'contact_lang` cl ON (cl.`id_contact` = a.`id_contact` AND cl.`id_lang` = '.(int)$cookie->id_lang.')'; $contactArray = array(); $contacts = Contact::getContacts($cookie->id_lang); foreach ($contacts AS $contact) $contactArray[$contact['id_contact']] = $contact['name']; $languageArray = array(); $languages = Language::getLanguages(); foreach ($languages AS $language) $languageArray[$language['id_lang']] = $language['name']; $statusArray = array( 'open' => $this->l('Open'), 'closed' => $this->l('Closed'), 'pending1' => $this->l('Pending 1'), 'pending2' => $this->l('Pending 2') ); $imagesArray = array( 'open' => 'status_green.gif', 'closed' => 'status_red.gif', 'pending1' => 'status_orange.gif', 'pending2' => 'status_orange.gif' ); $this->fieldsDisplay = array( 'id_customer_thread' => array('title' => $this->l('ID'), 'width' => 25), 'customer' => array('title' => $this->l('Customer'), 'width' => 100, 'filter_key' => 'customer', 'tmpTableFilter' => true), 'email' => array('title' => $this->l('E-mail'), 'width' => 100, 'filter_key' => 'a!email'), 'contact' => array('title' => $this->l('Type'), 'width' => 75, 'type' => 'select', 'select' => $contactArray, 'filter_key' => 'cl!id_contact', 'filter_type' => 'int'), 'language' => array('title' => $this->l('Language'), 'width' => 60, 'type' => 'select', 'select' => $languageArray, 'filter_key' => 'l!id_lang', 'filter_type' => 'int'), 'status' => array('title' => $this->l('Status'), 'width' => 50, 'type' => 'select', 'select' => $statusArray, 'icon' => $imagesArray, 'align' => 'center', 'filter_key' => 'a!status', 'filter_type' => 'string'), 'employee' => array('title' => $this->l('Employee'), 'width' => 100, 'filter_key' => 'employee', 'tmpTableFilter' => true), 'messages' => array('title' => $this->l('Messages'), 'width' => 50, 'filter_key' => 'messages', 'tmpTableFilter' => true, 'maxlength' => 0), 'date_upd' => array('title' => $this->l('Last message'), 'width' => 90) ); parent::__construct(); } public function postProcess() { global $currentIndex, $cookie, $link; if ($id_customer_thread = (int)Tools::getValue('id_customer_thread')) { if (($id_contact = (int)Tools::getValue('id_contact'))) Db::getInstance()->Execute('UPDATE '._DB_PREFIX_.'customer_thread SET id_contact = '.(int)$id_contact.' WHERE id_customer_thread = '.(int)$id_customer_thread); if ($id_status = (int)Tools::getValue('setstatus')) { $statusArray = array(1 => 'open', 2 => 'closed', 3 => 'pending1', 4 => 'pending2'); Db::getInstance()->Execute('UPDATE '._DB_PREFIX_.'customer_thread SET status = "'.$statusArray[$id_status].'" WHERE id_customer_thread = '.(int)$id_customer_thread.' LIMIT 1'); } if (isset($_POST['id_employee_forward'])) { // Todo: need to avoid doubles $messages = Db::getInstance()->ExecuteS(' SELECT ct.*, cm.*, cl.name subject, CONCAT(e.firstname, \' \', e.lastname) employee_name, CONCAT(c.firstname, \' \', c.lastname) customer_name, c.firstname FROM '._DB_PREFIX_.'customer_thread ct LEFT JOIN '._DB_PREFIX_.'customer_message cm ON (ct.id_customer_thread = cm.id_customer_thread) LEFT JOIN '._DB_PREFIX_.'contact_lang cl ON (cl.id_contact = ct.id_contact AND cl.id_lang = '.(int)$cookie->id_lang.') LEFT OUTER JOIN '._DB_PREFIX_.'employee e ON e.id_employee = cm.id_employee 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'); $output = ''; foreach ($messages AS $message) $output .= $this->displayMsg($message, true, (int)Tools::getValue('id_employee_forward')); $cm = new CustomerMessage(); $cm->id_employee = (int)$cookie->id_employee; $cm->id_customer_thread = (int)Tools::getValue('id_customer_thread'); $cm->ip_address = ip2long($_SERVER['REMOTE_ADDR']); $currentEmployee = new Employee($cookie->id_employee); if (($id_employee = (int)Tools::getValue('id_employee_forward')) AND ($employee = new Employee($id_employee)) AND Validate::isLoadedObject($employee)) { $params = array( '{messages}' => $output, '{employee}' => $currentEmployee->firstname.' '.$currentEmployee->lastname, '{comment}' => stripslashes($_POST['message_forward'])); if (Mail::Send((int)($cookie->id_lang), 'forward_msg', Mail::l('Fwd: Customer message'), $params, $employee->email, $employee->firstname.' '.$employee->lastname, $currentEmployee->email, $currentEmployee->firstname.' '.$currentEmployee->lastname, NULL, NULL, _PS_MAIL_DIR_, true)) { $cm->message = $this->l('Message forwarded to').' '.$employee->firstname.' '.$employee->lastname."\n".$this->l('Comment:').' '.$_POST['message_forward']; $cm->add(); } } elseif (($email = Tools::getValue('email')) AND Validate::isEmail($email)) { $params = array( '{messages}' => $output, '{employee}' => $currentEmployee->firstname.' '.$currentEmployee->lastname, '{comment}' => stripslashes($_POST['message_forward'])); if (Mail::Send((int)($cookie->id_lang), 'forward_msg', Mail::l('Fwd: Customer message'), $params, $email, NULL, $currentEmployee->email, $currentEmployee->firstname.' '.$currentEmployee->lastname, NULL, NULL, _PS_MAIL_DIR_, true)) { $cm->message = $this->l('Message forwarded to').' '.$email."\n".$this->l('Comment:').' '.$_POST['message_forward']; $cm->add(); } } else echo '
'.Tools::displayError('Email invalid.').'
'; } if (Tools::isSubmit('submitReply')) { $ct = new CustomerThread($id_customer_thread); $cm = new CustomerMessage(); $cm->id_employee = (int)$cookie->id_employee; $cm->id_customer_thread = $ct->id; $cm->message = Tools::htmlentitiesutf8(nl2br2(Tools::getValue('reply_message'))); $cm->ip_address = ip2long($_SERVER['REMOTE_ADDR']); if (isset($_FILES) AND !empty($_FILES['joinFile']['name']) AND $_FILES['joinFile']['error'] != 0) $this->_errors[] = Tools::displayError('An error occurred with the file upload.'); elseif ($cm->add()) { $fileAttachment = NULL; if (!empty($_FILES['joinFile']['name'])) { $fileAttachment['content'] = file_get_contents($_FILES['joinFile']['tmp_name']); $fileAttachment['name'] = $_FILES['joinFile']['name']; $fileAttachment['mime'] = $_FILES['joinFile']['type']; } $params = array( '{reply}' => nl2br2(Tools::getValue('reply_message')), '{link}' => $link->getPageLink('contact-form.php', true).'?id_customer_thread='.(int)($ct->id).'&token='.$ct->token); if (Mail::Send($ct->id_lang, 'reply_msg', Mail::l('An answer to your message is available'), $params, Tools::getValue('msg_email'), NULL, NULL, NULL, $fileAttachment, NULL, _PS_MAIL_DIR_, true)) { $ct->status = 'closed'; $ct->update(); } Tools::redirectAdmin($currentIndex.'&id_customer_thread='.(int)$id_customer_thread.'&viewcustomer_thread&token='.Tools::getValue('token')); } else $this->_errors[] = Tools::displayError('An error occurred, your message was not sent. Please contact your system administrator.'); } } return parent::postProcess(); } public function display() { global $cookie; if (isset($_GET['filename']) AND file_exists(_PS_UPLOAD_DIR_.$_GET['filename'])) self::openUploadedFile(); elseif (isset($_GET['view'.$this->table])) $this->viewcustomer_thread(); else { $this->getList((int)$cookie->id_lang, !Tools::getValue($this->table.'Orderby') ? 'date_upd' : NULL, !Tools::getValue($this->table.'Orderway') ? 'DESC' : NULL); $this->displayList(); } } public function displayListHeader($token = NULL) { global $currentIndex, $cookie; $contacts = Db::getInstance()->ExecuteS(' SELECT cl.*, COUNT(*) as total, ( SELECT id_customer_thread FROM '._DB_PREFIX_.'customer_thread ct2 WHERE status = "open" AND ct.id_contact = ct2.id_contact ORDER BY date_upd ASC LIMIT 1 ) as id_customer_thread FROM '._DB_PREFIX_.'customer_thread ct LEFT JOIN '._DB_PREFIX_.'contact_lang cl ON (cl.id_contact = ct.id_contact AND cl.id_lang = '.$cookie->id_lang.') WHERE ct.status = "open" GROUP BY ct.id_contact HAVING COUNT(*) > 0'); $categories = Db::getInstance()->ExecuteS(' SELECT cl.* FROM '._DB_PREFIX_.'contact ct LEFT JOIN '._DB_PREFIX_.'contact_lang cl ON (cl.id_contact = ct.id_contact AND cl.id_lang = '.$cookie->id_lang.') WHERE ct.customer_service = 1'); $dim = count($categories); echo '
'; foreach ($categories as $key => $val) { $totalThread = 0; $id_customer_thread = 0; foreach ($contacts as $tmp => $tmp2) if ($val['id_contact'] == $tmp2['id_contact']) { $totalThread = $tmp2['total']; $id_customer_thread = $tmp2['id_customer_thread']; break; } echo '

 '.$val['name'].'

'. ($dim > 6 ? '' : '

'.$val['description'].'

'). ($totalThread == 0 ? '

'.$this->l('No new message').'

' : ''.$totalThread.' '.($totalThread > 1 ? $this->l('new messages'): $this->l('new message')).'').'
'; } echo '
'; $params = array( $this->l('Total threads') => $all = Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_thread'), $this->l('Threads pending') => $pending = Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_thread WHERE status LIKE "%pending%"'), $this->l('Total customer messages') => Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_message WHERE id_employee = 0'), $this->l('Total employee messages') => Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_message WHERE id_employee != 0'), $this->l('Threads unread') => $unread = Db::getInstance()->getValue('SELECT COUNT(*) FROM '._DB_PREFIX_.'customer_thread WHERE status = "open"'), $this->l('Threads closed') => $all - ($unread + $pending)); echo '

'.$this->l('Customer service').' : '.$this->l('Statistics').'

'; $count = 0; foreach ($params as $key => $val) echo ''; echo '
'.$key.''.$val.'

 

'; parent::displayListHeader($token); } private function openUploadedFile() { $filename = $_GET['filename']; $extensions = array('.txt' => 'text/plain', '.rtf' => 'application/rtf', '.doc' => 'application/msword', '.docx'=> 'application/msword', '.pdf' => 'application/pdf', '.zip' => 'multipart/x-zip', '.png' => 'image/png', '.jpeg' => 'image/jpeg', '.gif' => 'image/gif', '.jpg' => 'image/jpeg'); $extension = ''; foreach ($extensions AS $key => $val) if (substr($filename, -4) == $key OR substr($filename, -5) == $key) { $extension = $val; break; } ob_end_clean(); header('Content-Type: '.$extension); header('Content-Disposition:attachment;filename="'.$filename.'"'); readfile(_PS_UPLOAD_DIR_.$filename); die; } private function displayMsg($message, $email = false, $id_employee = null) { global $cookie, $currentIndex; $customersToken = Tools::getAdminToken('AdminCustomers'.(int)(Tab::getIdFromClassName('AdminCustomers')).(int)($cookie->id_employee)); $contacts = Contact::getContacts($cookie->id_lang); if (!$email) { if (!empty($message['id_product']) AND empty($message['employee_name'])) $id_order_product = Db::getInstance()->getValue(' SELECT o.id_order FROM '._DB_PREFIX_.'orders o LEFT JOIN '._DB_PREFIX_.'order_detail od ON o.id_order = od.id_order WHERE o.id_customer = '.(int)$message['id_customer'].' AND od.product_id = '.(int)$message['id_product'].' ORDER BY o.date_add DESC'); $output = '
'.( !empty($message['employee_name']) ? ''.Configuration::get('PS_SHOP_NAME').' '.Configuration::get('PS_SHOP_NAME').' - '.$message['employee_name'] : ''.Configuration::get('PS_SHOP_NAME').' '.( !empty($message['id_customer']) ? ''.$message['customer_name'].'' : $message['email'] ) ).'
'.( (!empty($message['id_customer']) AND empty($message['employee_name'])) ? ''.$this->l('Customer ID:').' '.(int)($message['id_customer']).' '.$this->l('view').'
' : '' ).' '.$this->l('Sent on:').' '.Tools::displayDate($message['date_add'], (int)($cookie->id_lang), true).'
'.( empty($message['employee_name']) ? ''.$this->l('Browser:').' '.strip_tags($message['user_agent']).'
' : '' ).( (!empty($message['file_name']) AND file_exists(_PS_UPLOAD_DIR_.$message['file_name'])) ? ''.$this->l('File attachment').' '.$this->l('view').'
' : '' ).( (!empty($message['id_order']) AND empty($message['employee_name'])) ? ''.$this->l('Order #').' '.(int)($message['id_order']).' '.$this->l('view').'
' : '' ).( (!empty($message['id_product']) AND empty($message['employee_name'])) ? ''.$this->l('Product #').' '.(int)($message['id_product']).' '.$this->l('view').'
' : '' ).'
'.$this->l('Subject:').'
'; } else { $output = '
'.($id_employee ? ''.$this->l('View this thread').'
' : '').' '.$this->l('Sent by:').' '.(!empty($message['customer_name']) ? $message['customer_name'].' ('.$message['email'].')' : $message['email']) .((!empty($message['id_customer']) AND empty($message['employee_name'])) ? '
'.$this->l('Customer ID:').' '.(int)($message['id_customer']).'
' : '') .((!empty($message['id_order']) AND empty($message['employee_name'])) ? '
'.$this->l('Order #').': '.(int)($message['id_order']).'
' : '') .((!empty($message['id_product']) AND empty($message['employee_name'])) ? '
'.$this->l('Product #').': '.(int)($message['id_product']).'
' : '') .'
'.$this->l('Subject:').' '.$message['subject']; } $message['message'] = preg_replace('/(https?:\/\/[a-z0-9#%&_=\(\)\.\? \+\-@\/]{6,1000})([\s\n<])/Uui', '\1\2', html_entity_decode($message['message'], ENT_NOQUOTES, 'UTF-8')); $output .= '

'.$this->l('Thread ID:').' '.(int)$message['id_customer_thread'].'
'.$this->l('Message ID:').' '.(int)$message['id_customer_message'].'
'.$this->l('Message:').'
'.$message['message'].'
'; if (!$email) { if (empty($message['employee_name'])) $output .= '

'; } return $output; } public function viewcustomer_thread() { global $cookie, $currentIndex; if (!($thread = $this->loadObject())) return; $cookie->{'customer_threadFilter_cl!id_contact'} = $thread->id_contact; $employees = Db::getInstance()->ExecuteS(' SELECT e.id_employee, e.firstname, e.lastname FROM '._DB_PREFIX_.'employee e WHERE e.active = 1 ORDER BY e.lastname ASC'); echo '

'.$this->l('Messages').'

'.$this->l('Forward this discussion to an employee:').'

 
'; $messages = Db::getInstance()->ExecuteS(' SELECT ct.*, cm.*, cl.name subject, CONCAT(e.firstname, \' \', e.lastname) employee_name, CONCAT(c.firstname, \' \', c.lastname) customer_name, c.firstname FROM '._DB_PREFIX_.'customer_thread ct LEFT JOIN '._DB_PREFIX_.'customer_message cm ON (ct.id_customer_thread = cm.id_customer_thread) LEFT JOIN '._DB_PREFIX_.'contact_lang cl ON (cl.id_contact = ct.id_contact AND cl.id_lang = '.(int)$cookie->id_lang.') LEFT JOIN '._DB_PREFIX_.'employee e ON e.id_employee = cm.id_employee LEFT JOIN '._DB_PREFIX_.'customer c ON (IFNULL(ct.id_customer, ct.email) = IFNULL(c.id_customer, c.email)) WHERE ct.id_customer_thread = '.(int)Tools::getValue('id_customer_thread').' ORDER BY cm.date_add DESC'); echo '
'; $nextThread = Db::getInstance()->getValue(' SELECT id_customer_thread FROM '._DB_PREFIX_.'customer_thread ct WHERE ct.status = "open" AND ct.date_upd = ( SELECT date_add FROM '._DB_PREFIX_.'customer_message WHERE (id_employee IS NULL OR id_employee = 0) AND id_customer_thread = '.(int)$thread->id.' ORDER BY date_add DESC LIMIT 1 ) '.($cookie->{'customer_threadFilter_cl!id_contact'} ? 'AND ct.id_contact = '.(int)$cookie->{'customer_threadFilter_cl!id_contact'} : '').' '.($cookie->{'customer_threadFilter_l!id_lang'} ? 'AND ct.id_lang = '.(int)$cookie->{'customer_threadFilter_l!id_lang'} : ''). ' ORDER BY ct.date_upd ASC'); if ($nextThread) echo $this->displayButton('
'.$this->l('Answer to the next unanswered message in this category').' >
'); else echo $this->displayButton('
'.$this->l('The other messages in this category have been answered')); if ($thread->status != "closed") echo $this->displayButton('
'.$this->l('Set this message as handled').'
'); if ($thread->status != "pending1") echo $this->displayButton('
'.$this->l('Declare this message').'
'.$this->l('as "pending 1"').'
'.$this->l('(will be answered later)').'
'); else echo $this->displayButton('
'.$this->l('Click here to disable pending status').'
'); if ($thread->status != "pending2") echo $this->displayButton('
'.$this->l('Declare this message').'
'.$this->l('as "pending 2"').'
'.$this->l('(will be answered later)').'
'); else echo $this->displayButton('
'.$this->l('Click here to disable pending status').'
'); echo '
'; if ($thread->id_customer) { $customer = new Customer($thread->id_customer); $products = $customer->getBoughtProducts(); $orders = Order::getCustomerOrders($customer->id); echo '
'; if ($orders AND sizeof($orders)) { $totalOK = 0; $ordersOK = array(); $tokenOrders = Tools::getAdminToken('AdminOrders'.(int)(Tab::getIdFromClassName('AdminOrders')).(int)($cookie->id_employee)); foreach ($orders as $order) if ($order['valid']) { $ordersOK[] = $order; $totalOK += $order['total_paid_real']; } if ($countOK = sizeof($ordersOK)) { echo '

'.$this->l('Orders').'

'; $irow = 0; foreach ($ordersOK AS $order) echo ''; echo '
'.$this->l('ID').' '.$this->l('Date').' '.$this->l('Products').' '.$this->l('Total paid').' '.$this->l('Payment').' '.$this->l('State').' '.$this->l('Actions').'
'.$order['id_order'].' '.Tools::displayDate($order['date_add'], (int)($cookie->id_lang)).' '.$order['nb_products'].' '.Tools::displayPrice($order['total_paid_real'], new Currency((int)($order['id_currency']))).' '.$order['payment'].' '.$order['order_state'].'

'.$this->l('Validated Orders:').' '.$countOK.' '.$this->l('for').' '.Tools::displayPrice($totalOK, new Currency(Configuration::get('PS_CURRENCY_DEFAULT'))).'

'; } } if ($products AND sizeof($products)) { echo '

'.$this->l('Products').'

'; $irow = 0; $tokenOrders = Tools::getAdminToken('AdminOrders'.(int)(Tab::getIdFromClassName('AdminOrders')).(int)($cookie->id_employee)); foreach ($products AS $product) echo ' '; echo '
'.$this->l('Date').' '.$this->l('ID').' '.$this->l('Name').' '.$this->l('Quantity').' '.$this->l('Actions').'
'.Tools::displayDate($product['date_add'], (int)($cookie->id_lang), true).' '.$product['product_id'].' '.$product['product_name'].' '.$product['product_quantity'].'
'; } echo '
'; } echo '
'; foreach ($messages AS $message) echo $this->displayMsg($message); echo '
 
'; } private function displayButton($content) { return '

'.$content.'

'; } }