Merge pull request #20222 from thomas-Ngr/develop_new_ticket_notify_at_closing
New - Ticket: notify contacts at closing
This commit is contained in:
commit
0020f4e48a
@ -203,6 +203,12 @@ if ($action == 'setvarother') {
|
|||||||
if (!($res > 0)) {
|
if (!($res > 0)) {
|
||||||
$error++;
|
$error++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$param_auto_notify_close = GETPOST('TICKET_NOTIFY_AT_CLOSING', 'alpha');
|
||||||
|
$res = dolibarr_set_const($db, 'TICKET_NOTIFY_AT_CLOSING', $param_auto_notify_close, 'chaine', 0, '', $conf->entity);
|
||||||
|
if (!($res > 0)) {
|
||||||
|
$error++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -530,6 +536,21 @@ print $form->textwithpicto('', $langs->trans("TicketsAutoAssignTicketHelp"), 1,
|
|||||||
print '</td>';
|
print '</td>';
|
||||||
print '</tr>';
|
print '</tr>';
|
||||||
|
|
||||||
|
// Auto notify contacts when closing the ticket
|
||||||
|
print '<tr class="oddeven"><td>'.$langs->trans("TicketsAutoNotifyClose").'</td>';
|
||||||
|
print '<td class="left">';
|
||||||
|
if ($conf->use_javascript_ajax) {
|
||||||
|
print ajax_constantonoff('TICKET_NOTIFY_AT_CLOSING');
|
||||||
|
} else {
|
||||||
|
$arrval = array('0' => $langs->trans("No"), '1' => $langs->trans("Yes"));
|
||||||
|
print $form->selectarray("TICKET_NOTIFY_AT_CLOSING", $arrval, $conf->global->TICKET_NOTIFY_AT_CLOSING);
|
||||||
|
}
|
||||||
|
print '</td>';
|
||||||
|
print '<td class="center">';
|
||||||
|
print $form->textwithpicto('', $langs->trans("TicketsAutoNotifyCloseHelp"), 1, 'help');
|
||||||
|
print '</td>';
|
||||||
|
print '</tr>';
|
||||||
|
|
||||||
if (!$conf->use_javascript_ajax) {
|
if (!$conf->use_javascript_ajax) {
|
||||||
print '</form>';
|
print '</form>';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -109,7 +109,8 @@ class modTicket extends DolibarrModules
|
|||||||
3 => array('TICKET_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/tickets', 'Ticket templates ODT/ODS directory for templates', 0),
|
3 => array('TICKET_ADDON_PDF_ODT_PATH', 'chaine', 'DOL_DATA_ROOT/doctemplates/tickets', 'Ticket templates ODT/ODS directory for templates', 0),
|
||||||
4 => array('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'chaine', 0, 'Automatically mark ticket as read when created from backend', 0),
|
4 => array('TICKET_AUTO_READ_WHEN_CREATED_FROM_BACKEND', 'chaine', 0, 'Automatically mark ticket as read when created from backend', 0),
|
||||||
5 => array('TICKET_DELAY_BEFORE_FIRST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time before a first answer to a ticket (in hours). Display a warning in tickets list if not respected.', 0),
|
5 => array('TICKET_DELAY_BEFORE_FIRST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time before a first answer to a ticket (in hours). Display a warning in tickets list if not respected.', 0),
|
||||||
6 => array('TICKET_DELAY_SINCE_LAST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time between two answers on the same ticket (in hours). Display a warning in tickets list if not respected.', 0)
|
6 => array('TICKET_DELAY_SINCE_LAST_RESPONSE', 'chaine', '0', 'Maximum wanted elapsed time between two answers on the same ticket (in hours). Display a warning in tickets list if not respected.', 0),
|
||||||
|
7 => array('TICKET_NOTIFY_AT_CLOSING', 'chaine', '0', 'Default notify contacts when closing a module', 0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -133,71 +133,21 @@ class InterfaceTicketEmail extends DolibarrTriggers
|
|||||||
|
|
||||||
$langs->load('ticket');
|
$langs->load('ticket');
|
||||||
|
|
||||||
|
$subject_admin = 'TicketNewEmailSubjectAdmin';
|
||||||
|
$body_admin = 'TicketNewEmailBodyAdmin';
|
||||||
|
$subject_customer = 'TicketNewEmailSubjectCustomer';
|
||||||
|
$body_customer = 'TicketNewEmailBodyCustomer';
|
||||||
|
$see_ticket_customer = 'TicketNewEmailBodyInfosTrackUrlCustomer';
|
||||||
|
|
||||||
// Send email to notification email
|
// Send email to notification email
|
||||||
if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && empty($object->context['disableticketemail'])) {
|
if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && empty($object->context['disableticketemail'])) {
|
||||||
$sendto = empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) ? '' : $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
|
$sendto = empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) ? '' : $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
|
||||||
|
|
||||||
if ($sendto) {
|
if ($sendto) {
|
||||||
// Init to avoid errors
|
$this->composeAndSendAdminMessage($sendto, $subject_admin, $body_admin, $object, $langs, $conf);
|
||||||
$filepath = array();
|
|
||||||
$filename = array();
|
|
||||||
$mimetype = array();
|
|
||||||
|
|
||||||
/* Send email to admin */
|
|
||||||
$subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNewEmailSubjectAdmin');
|
|
||||||
$message_admin = $langs->transnoentities('TicketNewEmailBodyAdmin', $object->track_id).'<br><br>';
|
|
||||||
$message_admin .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
|
|
||||||
$message_admin .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
|
|
||||||
$message_admin .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
|
|
||||||
$message_admin .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
|
|
||||||
$message_admin .= '<li>'.$langs->trans('From').' : '.($object->email_from ? $object->email_from : ($object->fk_user_create > 0 ? $langs->trans('Internal') : '')).'</li>';
|
|
||||||
// Extrafields
|
|
||||||
$extraFields = new ExtraFields($this->db);
|
|
||||||
$extraFields->fetch_name_optionals_label($object->table_element);
|
|
||||||
if (is_array($object->array_options) && count($object->array_options) > 0) {
|
|
||||||
foreach ($object->array_options as $key => $value) {
|
|
||||||
$key = substr($key, 8); // remove "options_"
|
|
||||||
$message_admin .= '<li>'.$langs->trans($extraFields->attributes[$object->element]['label'][$key]).' : '.$extraFields->showOutputField($key, $value, '', $object->table_element).'</li>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$message_admin .= '</ul>';
|
|
||||||
|
|
||||||
if ($object->fk_soc > 0) {
|
|
||||||
$object->fetch_thirdparty();
|
|
||||||
$message_admin .= '<p>'.$langs->trans('Company').' : '.$object->thirdparty->name.'</p>';
|
|
||||||
}
|
|
||||||
|
|
||||||
$message = $object->message;
|
|
||||||
if (!dol_textishtml($message)) {
|
|
||||||
$message = dol_nl2br($message);
|
|
||||||
}
|
|
||||||
$message_admin .= '<p>'.$langs->trans('Message').' : <br>'.$message.'</p>';
|
|
||||||
$message_admin .= '<p><a href="'.dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id.'">'.$langs->trans('SeeThisTicketIntomanagementInterface').'</a></p>';
|
|
||||||
|
|
||||||
$from = $conf->global->MAIN_INFO_SOCIETE_NOM.'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
|
|
||||||
$replyto = $from;
|
|
||||||
|
|
||||||
$trackid = 'tic'.$object->id;
|
|
||||||
|
|
||||||
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
|
||||||
$old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
|
|
||||||
$conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
|
|
||||||
}
|
|
||||||
include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
|
|
||||||
$mailfile = new CMailFile($subject, $sendto, $from, $message_admin, $filepath, $mimetype, $filename, '', '', 0, -1, '', '', $trackid, '', 'ticket');
|
|
||||||
if ($mailfile->error) {
|
|
||||||
dol_syslog($mailfile->error, LOG_DEBUG);
|
|
||||||
} else {
|
|
||||||
$result = $mailfile->sendfile();
|
|
||||||
}
|
|
||||||
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
|
||||||
$conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send email to customer
|
// Send email to customer
|
||||||
|
|
||||||
if (empty($conf->global->TICKET_DISABLE_CUSTOMER_MAILS) && empty($object->context['disableticketemail']) && $object->notify_tiers_at_create) {
|
if (empty($conf->global->TICKET_DISABLE_CUSTOMER_MAILS) && empty($object->context['disableticketemail']) && $object->notify_tiers_at_create) {
|
||||||
$sendto = '';
|
$sendto = '';
|
||||||
|
|
||||||
@ -218,77 +168,7 @@ class InterfaceTicketEmail extends DolibarrTriggers
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($sendto) {
|
if ($sendto) {
|
||||||
// Init to avoid errors
|
$this->composeAndSendCustomerMessage($sendto, $subject_customer, $body_customer, $see_ticket_customer, $object, $langs, $conf);
|
||||||
$filepath = array();
|
|
||||||
$filename = array();
|
|
||||||
$mimetype = array();
|
|
||||||
|
|
||||||
$subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities('TicketNewEmailSubjectCustomer');
|
|
||||||
$message_customer = $langs->transnoentities('TicketNewEmailBodyCustomer', $object->track_id).'<br><br>';
|
|
||||||
$message_customer .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
|
|
||||||
$message_customer .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
|
|
||||||
$message_customer .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
|
|
||||||
$message_customer .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
|
|
||||||
|
|
||||||
// Extrafields
|
|
||||||
foreach ($this->attributes[$object->table_element]['label'] as $key => $value) {
|
|
||||||
$enabled = 1;
|
|
||||||
if ($enabled && isset($this->attributes[$object->table_element]['list'][$key])) {
|
|
||||||
$enabled = dol_eval($this->attributes[$object->table_element]['list'][$key], 1);
|
|
||||||
}
|
|
||||||
$perms = 1;
|
|
||||||
if ($perms && isset($this->attributes[$object->table_element]['perms'][$key])) {
|
|
||||||
$perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
$qualified = true;
|
|
||||||
if (empty($enabled)) {
|
|
||||||
$qualified = false;
|
|
||||||
}
|
|
||||||
if (empty($perms)) {
|
|
||||||
$qualified = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($qualified) {
|
|
||||||
$message_customer .= '<li>'.$langs->trans($key).' : '.$value.'</li>';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$message_customer .= '</ul>';
|
|
||||||
|
|
||||||
$message = $object->message;
|
|
||||||
if (!dol_textishtml($message)) {
|
|
||||||
$message = dol_nl2br($message);
|
|
||||||
}
|
|
||||||
$message_customer .= '<p>'.$langs->trans('Message').' : <br>'.$message.'</p>';
|
|
||||||
$url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id;
|
|
||||||
$message_customer .= '<p>'.$langs->trans('TicketNewEmailBodyInfosTrackUrlCustomer').' : <a href="'.$url_public_ticket.'">'.$url_public_ticket.'</a></p>';
|
|
||||||
$message_customer .= '<p>'.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'</p>';
|
|
||||||
|
|
||||||
$from = (empty($conf->global->MAIN_INFO_SOCIETE_NOM) ? '' : $conf->global->MAIN_INFO_SOCIETE_NOM.' ').'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
|
|
||||||
$replyto = $from;
|
|
||||||
|
|
||||||
$trackid = 'tic'.$object->id;
|
|
||||||
|
|
||||||
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
|
||||||
$old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
|
|
||||||
$conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
|
|
||||||
}
|
|
||||||
include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
|
|
||||||
$mailfile = new CMailFile($subject, $sendto, $from, $message_customer, $filepath, $mimetype, $filename, '', '', 0, -1, '', '', $trackid, '', 'ticket');
|
|
||||||
if ($mailfile->error) {
|
|
||||||
dol_syslog($mailfile->error, LOG_DEBUG);
|
|
||||||
} else {
|
|
||||||
$result = $mailfile->sendfile();
|
|
||||||
if ($result) {
|
|
||||||
// update last_msg_sent date
|
|
||||||
$object->date_last_msg_sent = dol_now();
|
|
||||||
$object->update($user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
|
||||||
$conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,10 +185,223 @@ class InterfaceTicketEmail extends DolibarrTriggers
|
|||||||
|
|
||||||
case 'TICKET_CLOSE':
|
case 'TICKET_CLOSE':
|
||||||
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
|
dol_syslog("Trigger '".$this->name."' for action '$action' launched by ".__FILE__.". id=".$object->id);
|
||||||
|
$langs->load('ticket');
|
||||||
|
|
||||||
|
$subject_admin = 'TicketCloseEmailSubjectAdmin';
|
||||||
|
$body_admin = 'TicketCloseEmailBodyAdmin';
|
||||||
|
$subject_customer = 'TicketCloseEmailSubjectCustomer';
|
||||||
|
$body_customer = 'TicketCloseEmailBodyCustomer';
|
||||||
|
$see_ticket_customer = 'TicketCloseEmailBodyInfosTrackUrlCustomer';
|
||||||
|
|
||||||
|
// Send email to notification email
|
||||||
|
if (!empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) && empty($object->context['disableticketemail'])) {
|
||||||
|
$sendto = empty($conf->global->TICKET_NOTIFICATION_EMAIL_TO) ? '' : $conf->global->TICKET_NOTIFICATION_EMAIL_TO;
|
||||||
|
if ($sendto) {
|
||||||
|
$this->composeAndSendAdminMessage($sendto, $subject_admin, $body_admin, $object, $langs, $conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send email to customer.
|
||||||
|
if (empty($conf->global->TICKET_DISABLE_CUSTOMER_MAILS) && empty($object->context['disableticketemail'])) {
|
||||||
|
$linked_contacts = $object->listeContact(-1, 'thirdparty');
|
||||||
|
$linked_contacts = array_merge($linked_contacts, $object->listeContact(-1, 'internal'));
|
||||||
|
if (empty($linked_contacts) && !empty($conf->global->TICKET_NOTIFY_AT_CLOSING) && !empty($object->fk_soc)) {
|
||||||
|
$object->fetch_thirdparty();
|
||||||
|
$linked_contacts[] = $object->thirdparty->email;
|
||||||
|
}
|
||||||
|
|
||||||
|
$contactid = GETPOST('contactid', 'int');
|
||||||
|
if ($contactid > 0) {
|
||||||
|
$contact = new Contact($this->db);
|
||||||
|
$res = $contact->fetch($contactid);
|
||||||
|
if (! in_array($contact, $linked_contacts)) {
|
||||||
|
$error_msg = $langs->trans('Error'). ': ';
|
||||||
|
$error_msg .= $langs->transnoentities('TicketWrongContact');
|
||||||
|
setEventMessages($error_msg, [], 'errors');
|
||||||
|
$ok = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$sendto = '';
|
||||||
|
if ($res > 0 && !empty($contact->email) && !empty($contact->statut)) {
|
||||||
|
$sendto = $contact->email;
|
||||||
|
} elseif ( !empty($linked_contacts) && ($contactid == -2 || (GETPOST('massaction', 'alpha') == 'close' && GETPOST('confirm', 'alpha') == 'yes'))) {
|
||||||
|
// if sending to all contacts or sending to contacts while mass closing
|
||||||
|
$temp_emails = [];
|
||||||
|
foreach ($linked_contacts as $contact) {
|
||||||
|
$temp_emails[] = $contact['email'];
|
||||||
|
}
|
||||||
|
$sendto = implode(", ", $temp_emails);
|
||||||
|
unset($temp_emails);
|
||||||
|
unset($linked_contacts);
|
||||||
|
}
|
||||||
|
if ($sendto) {
|
||||||
|
$this->composeAndSendCustomerMessage($sendto, $subject_customer, $body_customer, $see_ticket_customer, $object, $langs, $conf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$ok = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return $ok;
|
return $ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composes and sends a message concerning a ticket, to be sent to admin address.
|
||||||
|
* @param string $sendto Addresses to send the mail, format "first@address.net, second@address.net," etc.
|
||||||
|
* @param string $base_subject email subject. Non-translated string.
|
||||||
|
* @param string $body email body (first line). Non-translated string.
|
||||||
|
* @param Ticket $object the ticket thet the email refers to
|
||||||
|
* @param Translate $langs the translation object
|
||||||
|
* @param conf $conf Object conf
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
private function composeAndSendAdminMessage($sendto, $base_subject, $body, Ticket $object, Translate $langs, $conf)
|
||||||
|
{
|
||||||
|
// Init to avoid errors
|
||||||
|
$filepath = array();
|
||||||
|
$filename = array();
|
||||||
|
$mimetype = array();
|
||||||
|
|
||||||
|
/* Send email to admin */
|
||||||
|
$subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities($base_subject, $object->ref, $object->track_id);
|
||||||
|
$message_admin = $langs->transnoentities($body, $object->track_id).'<br>';
|
||||||
|
$message_admin .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
|
||||||
|
$message_admin .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
|
||||||
|
$message_admin .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
|
||||||
|
$message_admin .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
|
||||||
|
$message_admin .= '<li>'.$langs->trans('From').' : '.($object->email_from ? $object->email_from : ($object->fk_user_create > 0 ? $langs->trans('Internal') : '')).'</li>';
|
||||||
|
// Extrafields
|
||||||
|
$extraFields = new ExtraFields($this->db);
|
||||||
|
$extraFields->fetch_name_optionals_label($object->table_element);
|
||||||
|
if (is_array($object->array_options) && count($object->array_options) > 0) {
|
||||||
|
foreach ($object->array_options as $key => $value) {
|
||||||
|
$key = substr($key, 8); // remove "options_"
|
||||||
|
$message_admin .= '<li>'.$langs->trans($extraFields->attributes[$object->element]['label'][$key]).' : '.$extraFields->showOutputField($key, $value, '', $object->table_element).'</li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($object->fk_soc > 0) {
|
||||||
|
$object->fetch_thirdparty();
|
||||||
|
$message_admin .= '<li>'.$langs->trans('Company').' : '.$object->thirdparty->name.'</li>';
|
||||||
|
}
|
||||||
|
$message_admin .= '</ul>';
|
||||||
|
|
||||||
|
$message = $object->message;
|
||||||
|
if (!dol_textishtml($message)) {
|
||||||
|
$message = dol_nl2br($message);
|
||||||
|
}
|
||||||
|
$message_admin .= '<p>'.$langs->trans('Message').' : <br><br>'.$message.'</p><br>';
|
||||||
|
$message_admin .= '<p><a href="'.dol_buildpath('/ticket/card.php', 2).'?track_id='.$object->track_id.'">'.$langs->trans('SeeThisTicketIntomanagementInterface').'</a></p>';
|
||||||
|
|
||||||
|
$from = $conf->global->MAIN_INFO_SOCIETE_NOM.'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
|
||||||
|
|
||||||
|
$trackid = 'tic'.$object->id;
|
||||||
|
|
||||||
|
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
||||||
|
$old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
|
||||||
|
$conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
|
||||||
|
}
|
||||||
|
include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
|
||||||
|
$mailfile = new CMailFile($subject, $sendto, $from, $message_admin, $filepath, $mimetype, $filename, '', '', 0, -1, '', '', $trackid, '', 'ticket');
|
||||||
|
if ($mailfile->error) {
|
||||||
|
dol_syslog($mailfile->error, LOG_DEBUG);
|
||||||
|
} else {
|
||||||
|
$result = $mailfile->sendfile();
|
||||||
|
}
|
||||||
|
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
||||||
|
$conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Composes and sends a message concerning a ticket, to be sent to customer addresses.
|
||||||
|
* @param string $sendto Addresses to send the mail, format "first@address.net, second@address.net, " etc.
|
||||||
|
* @param string $base_subject email subject. Non-translated string.
|
||||||
|
* @param string $body email body (first line). Non-translated string.
|
||||||
|
* @param string $see_ticket string indicating the ticket public address
|
||||||
|
* @param Ticket $object the ticket thet the email refers to
|
||||||
|
* @param Translate $langs the translation object
|
||||||
|
* @param conf $conf Object conf
|
||||||
|
*
|
||||||
|
* @return none
|
||||||
|
*/
|
||||||
|
private function composeAndSendCustomerMessage($sendto, $base_subject, $body, $see_ticket, Ticket $object, Translate $langs, $conf)
|
||||||
|
{
|
||||||
|
// Init to avoid errors
|
||||||
|
$filepath = array();
|
||||||
|
$filename = array();
|
||||||
|
$mimetype = array();
|
||||||
|
|
||||||
|
$subject = '['.$conf->global->MAIN_INFO_SOCIETE_NOM.'] '.$langs->transnoentities($base_subject);
|
||||||
|
$message_customer = $langs->transnoentities($body, $object->track_id).'<br>';
|
||||||
|
$message_customer .= '<ul><li>'.$langs->trans('Title').' : '.$object->subject.'</li>';
|
||||||
|
$message_customer .= '<li>'.$langs->trans('Type').' : '.$langs->getLabelFromKey($this->db, 'TicketTypeShort'.$object->type_code, 'c_ticket_type', 'code', 'label', $object->type_code).'</li>';
|
||||||
|
$message_customer .= '<li>'.$langs->trans('Category').' : '.$langs->getLabelFromKey($this->db, 'TicketCategoryShort'.$object->category_code, 'c_ticket_category', 'code', 'label', $object->category_code).'</li>';
|
||||||
|
$message_customer .= '<li>'.$langs->trans('Severity').' : '.$langs->getLabelFromKey($this->db, 'TicketSeverityShort'.$object->severity_code, 'c_ticket_severity', 'code', 'label', $object->severity_code).'</li>';
|
||||||
|
|
||||||
|
// Extrafields
|
||||||
|
if (is_array($this->attributes[$object->table_element]['label'])) {
|
||||||
|
foreach ($this->attributes[$object->table_element]['label'] as $key => $value) {
|
||||||
|
$enabled = 1;
|
||||||
|
if ($enabled && isset($this->attributes[$object->table_element]['list'][$key])) {
|
||||||
|
$enabled = dol_eval($this->attributes[$object->table_element]['list'][$key], 1);
|
||||||
|
}
|
||||||
|
$perms = 1;
|
||||||
|
if ($perms && isset($this->attributes[$object->table_element]['perms'][$key])) {
|
||||||
|
$perms = dol_eval($this->attributes[$object->table_element]['perms'][$key], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$qualified = true;
|
||||||
|
if (empty($enabled)) {
|
||||||
|
$qualified = false;
|
||||||
|
}
|
||||||
|
if (empty($perms)) {
|
||||||
|
$qualified = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($qualified) {
|
||||||
|
$message_customer .= '<li>' . $langs->trans($key) . ' : ' . $value . '</li>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$message_customer .= '</ul>';
|
||||||
|
|
||||||
|
$message = $object->message;
|
||||||
|
if (!dol_textishtml($message)) {
|
||||||
|
$message = dol_nl2br($message);
|
||||||
|
}
|
||||||
|
$message_customer .= '<p>'.$langs->trans('Message').' : <br><br>'.$message.'</p><br>';
|
||||||
|
$url_public_ticket = ($conf->global->TICKET_URL_PUBLIC_INTERFACE ? $conf->global->TICKET_URL_PUBLIC_INTERFACE.'/' : dol_buildpath('/public/ticket/view.php', 2)).'?track_id='.$object->track_id;
|
||||||
|
$message_customer .= '<p>'.$langs->trans($see_ticket).' : <a href="'.$url_public_ticket.'">'.$url_public_ticket.'</a></p>';
|
||||||
|
$message_customer .= '<p>'.$langs->trans('TicketEmailPleaseDoNotReplyToThisEmail').'</p>';
|
||||||
|
|
||||||
|
$from = (empty($conf->global->MAIN_INFO_SOCIETE_NOM) ? '' : $conf->global->MAIN_INFO_SOCIETE_NOM.' ').'<'.$conf->global->TICKET_NOTIFICATION_EMAIL_FROM.'>';
|
||||||
|
|
||||||
|
$trackid = 'tic'.$object->id;
|
||||||
|
|
||||||
|
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
||||||
|
$old_MAIN_MAIL_AUTOCOPY_TO = $conf->global->MAIN_MAIL_AUTOCOPY_TO;
|
||||||
|
$conf->global->MAIN_MAIL_AUTOCOPY_TO = '';
|
||||||
|
}
|
||||||
|
include_once DOL_DOCUMENT_ROOT.'/core/class/CMailFile.class.php';
|
||||||
|
$mailfile = new CMailFile($subject, $sendto, $from, $message_customer, $filepath, $mimetype, $filename, '', '', 0, -1, '', '', $trackid, '', 'ticket');
|
||||||
|
if ($mailfile->error) {
|
||||||
|
dol_syslog($mailfile->error, LOG_DEBUG);
|
||||||
|
} else {
|
||||||
|
$result = $mailfile->sendfile();
|
||||||
|
if ($result) {
|
||||||
|
// update last_msg_sent date
|
||||||
|
$object->fetch($object->id);
|
||||||
|
$object->date_last_msg_sent = dol_now();
|
||||||
|
$object->update($user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!empty($conf->global->TICKET_DISABLE_MAIL_AUTOCOPY_TO)) {
|
||||||
|
$conf->global->MAIN_MAIL_AUTOCOPY_TO = $old_MAIN_MAIL_AUTOCOPY_TO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -142,6 +142,9 @@ TicketsDelayBeforeFirstAnswer=A new ticket should receive a first answer before
|
|||||||
TicketsDelayBeforeFirstAnswerHelp=If a new ticket has not received an answer after this time period (in hours), an important warning icon will be displayed in the list view.
|
TicketsDelayBeforeFirstAnswerHelp=If a new ticket has not received an answer after this time period (in hours), an important warning icon will be displayed in the list view.
|
||||||
TicketsDelayBetweenAnswers=An unresolved ticket should not be unactive during (hours):
|
TicketsDelayBetweenAnswers=An unresolved ticket should not be unactive during (hours):
|
||||||
TicketsDelayBetweenAnswersHelp=If an unresolved ticket that has already received an answer has not had further interaction after this time period (in hours), a warning icon will be displayed in the list view.
|
TicketsDelayBetweenAnswersHelp=If an unresolved ticket that has already received an answer has not had further interaction after this time period (in hours), a warning icon will be displayed in the list view.
|
||||||
|
TicketsAutoNotifyClose=Automatically notify thirdparty when closing a ticket
|
||||||
|
TicketsAutoNotifyCloseHelp=When closing a ticket, you will be proposed to send a message to one of thirdparty's contacts. On mass closing, a message will be sent to one contact of the thirdparty linked to the ticket.
|
||||||
|
TicketWrongContact=Provided contact is not part of current ticket contacts. Email not sent.
|
||||||
|
|
||||||
#
|
#
|
||||||
# Index & list page
|
# Index & list page
|
||||||
@ -158,6 +161,8 @@ OrderByDateAsc=Sort by ascending date
|
|||||||
OrderByDateDesc=Sort by descending date
|
OrderByDateDesc=Sort by descending date
|
||||||
ShowAsConversation=Show as conversation list
|
ShowAsConversation=Show as conversation list
|
||||||
MessageListViewType=Show as table list
|
MessageListViewType=Show as table list
|
||||||
|
ConfirmMassTicketClosingSendEmail=Automatically send emails when closing tickets
|
||||||
|
ConfirmMassTicketClosingSendEmailQuestion=Do you want to notify thirdparties when closing these tickets ?
|
||||||
|
|
||||||
#
|
#
|
||||||
# Ticket card
|
# Ticket card
|
||||||
@ -245,6 +250,9 @@ TicketChangeStatus=Change status
|
|||||||
TicketConfirmChangeStatus=Confirm the status change: %s ?
|
TicketConfirmChangeStatus=Confirm the status change: %s ?
|
||||||
TicketLogStatusChanged=Status changed: %s to %s
|
TicketLogStatusChanged=Status changed: %s to %s
|
||||||
TicketNotNotifyTiersAtCreate=Not notify company at create
|
TicketNotNotifyTiersAtCreate=Not notify company at create
|
||||||
|
NotifyThirdpartyOnTicketClosing=Contacts to notify while closing the ticket
|
||||||
|
TicketNotifyAllTiersAtClose=All related contacts
|
||||||
|
TicketNotNotifyTiersAtClose=No related contact
|
||||||
Unread=Unread
|
Unread=Unread
|
||||||
TicketNotCreatedFromPublicInterface=Not available. Ticket was not created from public interface.
|
TicketNotCreatedFromPublicInterface=Not available. Ticket was not created from public interface.
|
||||||
ErrorTicketRefRequired=Ticket reference name is required
|
ErrorTicketRefRequired=Ticket reference name is required
|
||||||
@ -279,6 +287,7 @@ TicketNewEmailBodyInfosTicket=Information for monitoring the ticket
|
|||||||
TicketNewEmailBodyInfosTrackId=Ticket tracking number: %s
|
TicketNewEmailBodyInfosTrackId=Ticket tracking number: %s
|
||||||
TicketNewEmailBodyInfosTrackUrl=You can view the progress of the ticket by clicking the link above.
|
TicketNewEmailBodyInfosTrackUrl=You can view the progress of the ticket by clicking the link above.
|
||||||
TicketNewEmailBodyInfosTrackUrlCustomer=You can view the progress of the ticket in the specific interface by clicking the following link
|
TicketNewEmailBodyInfosTrackUrlCustomer=You can view the progress of the ticket in the specific interface by clicking the following link
|
||||||
|
TicketCloseEmailBodyInfosTrackUrlCustomer=You can consult the history of this ticket by clicking the following link
|
||||||
TicketEmailPleaseDoNotReplyToThisEmail=Please do not reply directly to this email! Use the link to reply into the interface.
|
TicketEmailPleaseDoNotReplyToThisEmail=Please do not reply directly to this email! Use the link to reply into the interface.
|
||||||
TicketPublicInfoCreateTicket=This form allows you to record a support ticket in our management system.
|
TicketPublicInfoCreateTicket=This form allows you to record a support ticket in our management system.
|
||||||
TicketPublicPleaseBeAccuratelyDescribe=Please accurately describe the problem. Provide the most information possible to allow us to correctly identify your request.
|
TicketPublicPleaseBeAccuratelyDescribe=Please accurately describe the problem. Provide the most information possible to allow us to correctly identify your request.
|
||||||
@ -300,6 +309,10 @@ NewUser=New user
|
|||||||
NumberOfTicketsByMonth=Number of tickets per month
|
NumberOfTicketsByMonth=Number of tickets per month
|
||||||
NbOfTickets=Number of tickets
|
NbOfTickets=Number of tickets
|
||||||
# notifications
|
# notifications
|
||||||
|
TicketCloseEmailSubjectCustomer=Ticket closed
|
||||||
|
TicketCloseEmailBodyCustomer=This is an automatic message to notify you that ticket %s has just been closed.
|
||||||
|
TicketCloseEmailSubjectAdmin=Ticket closed - Réf %s (public ticket ID %s)
|
||||||
|
TicketCloseEmailBodyAdmin=A ticket with ID #%s has just been closed, see information:
|
||||||
TicketNotificationEmailSubject=Ticket %s updated
|
TicketNotificationEmailSubject=Ticket %s updated
|
||||||
TicketNotificationEmailBody=This is an automatic message to notify you that ticket %s has just been updated
|
TicketNotificationEmailBody=This is an automatic message to notify you that ticket %s has just been updated
|
||||||
TicketNotificationRecipient=Notification recipient
|
TicketNotificationRecipient=Notification recipient
|
||||||
|
|||||||
@ -820,10 +820,28 @@ if ($action == 'create' || $action == 'presend') {
|
|||||||
|
|
||||||
// Confirmation close
|
// Confirmation close
|
||||||
if ($action == 'close') {
|
if ($action == 'close') {
|
||||||
print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", '', '', 1);
|
$thirdparty_contacts = $object->getInfosTicketExternalContact();
|
||||||
if ($ret == 'html') {
|
$contacts_select = array(
|
||||||
print '<br>';
|
'-2' => $langs->trans('TicketNotifyAllTiersAtClose'),
|
||||||
|
'-3' => $langs->trans('TicketNotNotifyTiersAtClose')
|
||||||
|
);
|
||||||
|
foreach ($thirdparty_contacts as $thirdparty_contact) {
|
||||||
|
$contacts_select[$thirdparty_contact['id']] = $thirdparty_contact['civility'] . ' ' . $thirdparty_contact['lastname'] . ' ' . $thirdparty_contact['firstname'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default select all or no contact
|
||||||
|
$default = (!empty($conf->global->TICKET_NOTIFY_AT_CLOSING)) ? -2 : -3;
|
||||||
|
$formquestion = array(
|
||||||
|
array(
|
||||||
|
'name' => 'contactid',
|
||||||
|
'type' => 'select',
|
||||||
|
'label' => $langs->trans('NotifyThirdpartyOnTicketClosing'),
|
||||||
|
'values' => $contacts_select,
|
||||||
|
'default' => $default
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
print $form->formconfirm($url_page_current."?track_id=".$object->track_id, $langs->trans("CloseATicket"), $langs->trans("ConfirmCloseAticket"), "confirm_close", $formquestion, '', 1);
|
||||||
}
|
}
|
||||||
// Confirmation abandon
|
// Confirmation abandon
|
||||||
if ($action == 'abandon') {
|
if ($action == 'abandon') {
|
||||||
|
|||||||
@ -185,7 +185,7 @@ if (GETPOST('cancel', 'alpha')) {
|
|||||||
$action = 'list';
|
$action = 'list';
|
||||||
$massaction = '';
|
$massaction = '';
|
||||||
}
|
}
|
||||||
if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
|
if (!GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend' && $massaction != 'presendonclose' && $massaction != 'close') {
|
||||||
$massaction = '';
|
$massaction = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -690,7 +690,7 @@ $arrayofmassactions = array(
|
|||||||
//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
|
//'builddoc'=>img_picto('', 'pdf', 'class="pictofixedwidth"').$langs->trans("PDFMerge"),
|
||||||
);
|
);
|
||||||
if ($permissiontoadd) {
|
if ($permissiontoadd) {
|
||||||
$arrayofmassactions['close'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Close");
|
$arrayofmassactions['presendonclose'] = img_picto('', 'close_title', 'class="pictofixedwidth"').$langs->trans("Close");
|
||||||
$arrayofmassactions['reopen'] = img_picto('', 'folder-open', 'class="pictofixedwidth"').$langs->trans("ReOpen");
|
$arrayofmassactions['reopen'] = img_picto('', 'folder-open', 'class="pictofixedwidth"').$langs->trans("ReOpen");
|
||||||
}
|
}
|
||||||
if ($permissiontodelete) {
|
if ($permissiontodelete) {
|
||||||
@ -743,6 +743,17 @@ $objecttmp = new Ticket($db);
|
|||||||
$trackid = 'tic'.$object->id;
|
$trackid = 'tic'.$object->id;
|
||||||
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
|
include DOL_DOCUMENT_ROOT.'/core/tpl/massactions_pre.tpl.php';
|
||||||
|
|
||||||
|
// confirm auto send on close
|
||||||
|
if ($massaction == 'presendonclose') {
|
||||||
|
$hidden_form = array([
|
||||||
|
"type" => "hidden",
|
||||||
|
"name" => "massaction",
|
||||||
|
"value" => "close"
|
||||||
|
]);
|
||||||
|
$selectedchoice = (!empty($conf->global->TICKET_NOTIFY_AT_CLOSING)) ? "yes" : "no";
|
||||||
|
print $form->formconfirm($_SERVER["PHP_SELF"], $langs->trans("ConfirmMassTicketClosingSendEmail"), $langs->trans("ConfirmMassTicketClosingSendEmailQuestion"), 'confirm_send_close', $hidden_form, $selectedchoice, 0, 200, 500, 1);
|
||||||
|
}
|
||||||
|
|
||||||
if ($search_all) {
|
if ($search_all) {
|
||||||
foreach ($fieldstosearchall as $key => $val) {
|
foreach ($fieldstosearchall as $key => $val) {
|
||||||
$fieldstosearchall[$key] = $langs->trans($val);
|
$fieldstosearchall[$key] = $langs->trans($val);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user