diff --git a/.gitignore b/.gitignore index 70d3d8c3..44ac5da8 100644 --- a/.gitignore +++ b/.gitignore @@ -8,7 +8,6 @@ admin/archive.php admin/custom_statuses.php admin/email_templates.php admin/generate_spam_question.php -admin/priority.php admin/test_connection.php attachments/index.htm cache/ diff --git a/admin/admin_reply_ticket.php b/admin/admin_reply_ticket.php index 96ab9f9f..29a0d5c8 100644 --- a/admin/admin_reply_ticket.php +++ b/admin/admin_reply_ticket.php @@ -189,15 +189,20 @@ if ($hesk_settings['attachments']['use'] && !empty($attachments)) { // Add reply $html = $modsForHesk_settings['rich_text_for_tickets']; if ($submit_as_customer) { - hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "

{$hesklang['creb']} {$_SESSION['name']}") . "',NOW(),'" . hesk_dbEscape($myattachments) . "', '" . $html . "')"); + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($ticket['name'])) . "','" . hesk_dbEscape($message . "

{$hesklang['creb']} {$_SESSION['name']}") . "','" . hesk_dbEscape(hesk_date()) . "','" . hesk_dbEscape($myattachments) . "', '" . $html . "')"); } else { - hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "',NOW(),'" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')"); + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` (`replyto`,`name`,`message`,`dt`,`attachments`,`staffid`,`html`) VALUES ('" . intval($replyto) . "','" . hesk_dbEscape(addslashes($_SESSION['name'])) . "','" . hesk_dbEscape($message) . "','" . hesk_dbEscape(hesk_date()) . "','" . hesk_dbEscape($myattachments) . "','" . intval($_SESSION['id']) . "', '" . $html . "')"); } /* Track ticket status changes for history */ $revision = ''; /* Change the status of priority? */ +$audit_priority = null; +$audit_closed = null; +$audit_status = null; +$audit_customer_status = null; +$audit_assigned_self = null; if (!empty($_POST['set_priority'])) { $priority = intval(hesk_POST('priority')); if ($priority < 0 || $priority > 3) { @@ -211,9 +216,17 @@ if (!empty($_POST['set_priority'])) { 3 => $hesklang['low'] ); - $revision = sprintf($hesklang['thist8'], hesk_date(), $options[$priority], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); + $plain_options = array( + 0 => 'critical', + 1 => 'high', + 2 => 'medium', + 3 => 'low' + ); - $priority_sql = ",`priority`='$priority', `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $priority_sql = ",`priority`='$priority' "; + + $audit_priority = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => $plain_options[$priority]); } else { $priority_sql = ""; } @@ -238,8 +251,11 @@ if ($ticket['locked']) { $newStatus = hesk_dbFetchAssoc($newStatusRs); if ($newStatus['IsClosed'] && hesk_checkPermission('can_resolve', 0)) { - $revision = sprintf($hesklang['thist3'], hesk_date(), $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql_status = " , `closedat`=NOW(), `closedby`=" . intval($_SESSION['id']) . ", `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_closed = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); + $audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => mfh_getDisplayTextForStatusId($new_status) + ); + $sql_status = " , `closedat`=NOW(), `closedby`=" . intval($_SESSION['id']) . " "; // Lock the ticket if customers are not allowed to reopen tickets if ($hesk_settings['custopen'] != 1) { @@ -247,8 +263,8 @@ if ($ticket['locked']) { } } else { // Ticket isn't being closed, just add the history to the sql query (or tried to close but doesn't have permission) - $revision = sprintf($hesklang['thist9'], hesk_date(), $hesklang[$newStatus['Key']], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql_status = " , `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => mfh_getDisplayTextForStatusId($new_status)); } } } // -> Submit as Customer reply @@ -259,8 +275,8 @@ elseif ($submit_as_customer) { $new_status = $customerReplyStatus['ID']; if ($ticket['status'] != $new_status) { - $revision = sprintf($hesklang['thist9'], hesk_date(), $hesklang['wait_reply'], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql_status = " , `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_customer_status = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => mfh_getDisplayTextForStatusId($new_status)); } } // -> Default: submit as "Replied by staff" else { @@ -282,8 +298,8 @@ if ($time_worked == '00:00:00') { } if (!empty($_POST['assign_self']) && (hesk_checkPermission('can_assign_self', 0) || (isset($_REQUEST['isManager']) && $_REQUEST['isManager']))) { - $revision = sprintf($hesklang['thist2'], hesk_date(), $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - $sql .= " , `owner`=" . intval($_SESSION['id']) . ", `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') "; + $audit_assigned_self = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); + $sql .= " , `owner`=" . intval($_SESSION['id']) . " "; } $sql .= " $priority_sql "; @@ -306,6 +322,29 @@ unset($sql); /* Update number of replies in the users table */ hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "users` SET `replies`=`replies`+1 WHERE `id`='" . intval($_SESSION['id']) . "'"); +//-- Insert necessary audit trail records +if ($audit_priority != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_priority', hesk_date(), $audit_priority); +} + +if ($audit_closed != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_closed', hesk_date(), $audit_closed); +} + +if ($audit_status != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_status', hesk_date(), $audit_status); +} + +if ($audit_customer_status != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_status', hesk_date(), + $audit_customer_status); +} + +if ($audit_assigned_self != null) { + mfh_insert_audit_trail_record($replyto, 'TICKET', 'audit_assigned_self', hesk_date(), $audit_assigned_self); +} + + // --> Prepare reply message // 1. Generate the array with ticket info that can be used in emails diff --git a/admin/admin_submit_ticket.php b/admin/admin_submit_ticket.php index 9eb40c3a..80d1269e 100644 --- a/admin/admin_submit_ticket.php +++ b/admin/admin_submit_ticket.php @@ -176,11 +176,11 @@ foreach ($hesk_settings['custom_fields'] as $k=>$v) { $tmpvar['trackid'] = hesk_createID(); // Log who submitted ticket -$tmpvar['history'] = sprintf($hesklang['thist7'], hesk_date(), $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); $tmpvar['openedby'] = $_SESSION['id']; // Owner $tmpvar['owner'] = 0; +$autoassign_owner = null; if (hesk_checkPermission('can_assign_others', 0)) { $tmpvar['owner'] = intval(hesk_POST('owner')); @@ -192,7 +192,6 @@ if (hesk_checkPermission('can_assign_others', 0)) { $autoassign_owner = hesk_autoAssignTicket($tmpvar['category']); if ($autoassign_owner) { $tmpvar['owner'] = intval($autoassign_owner['id']); - $tmpvar['history'] .= sprintf($hesklang['thist10'], hesk_date(), $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')'); } else { $tmpvar['owner'] = 0; } @@ -315,6 +314,14 @@ $tmpvar['screen_resolution_width'] = "NULL"; // Insert ticket to database $ticket = hesk_newTicket($tmpvar); +mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_created', hesk_date(), + array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')')); + +if ($autoassign_owner) { + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(), + array(0 => $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')')); +} + // Notify the customer about the ticket? if ($notify && $email_available) { hesk_notifyCustomer($modsForHesk_settings); diff --git a/admin/admin_ticket.php b/admin/admin_ticket.php index 9743f626..d17ee27b 100644 --- a/admin/admin_ticket.php +++ b/admin/admin_ticket.php @@ -97,6 +97,37 @@ if (!$ticket['owner'] && !$can_view_unassigned) { hesk_error($hesklang['ycovtay']); } +// Get audit information +$audit_sort = $hesk_settings['new_top'] ? "ASC" : "DESC"; +$auditRes = hesk_dbQuery("SELECT `audit`.`id`, `audit`.`language_key`, `audit`.`date`, + `values`.`replacement_index`, `values`.`replacement_value` + FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` AS `audit` + LEFT JOIN `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail_to_replacement_values` AS `values` + ON `audit`.`id` = `values`.`audit_trail_id` + WHERE `entity_type` = 'TICKET' AND `entity_id` = " . intval($ticket['id']) . " + ORDER BY `audit`.`date` {$audit_sort}"); +$audit_records = array(); +$current_audit_record = null; +while ($row = hesk_dbFetchAssoc($auditRes)) { + if ($current_audit_record == null || $current_audit_record['id'] != $row['id']) { + if ($current_audit_record != null) { + $audit_records[] = $current_audit_record; + } + $current_audit_record['id'] = $row['id']; + $current_audit_record['language_key'] = $row['language_key']; + $current_audit_record['date'] = $row['date']; + $current_audit_record['replacement_values'] = array(); + } + + if ($row['replacement_index'] != null) { + $current_audit_record['replacement_values'][intval($row['replacement_index'])] = $row['replacement_value']; + } +} + +if ($current_audit_record != null) { + $audit_records[] = $current_audit_record; +} + /* Set last replier name */ if ($ticket['lastreplier']) { if (empty($ticket['repliername'])) { @@ -439,8 +470,10 @@ if ($hesk_settings['time_worked'] && ($can_reply || $can_edit) && isset($_POST[' $time_worked = hesk_getTime($h . ':' . $m . ':' . $s); /* Update database */ - $revision = sprintf($hesklang['thist14'], hesk_date(), $time_worked, $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); - hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `time_worked`='" . hesk_dbEscape($time_worked) . "', `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); + hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `time_worked`='" . hesk_dbEscape($time_worked) . "' WHERE `trackid`='" . hesk_dbEscape($trackingID) . "'"); + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_time_worked', hesk_date(), + array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => $time_worked)); /* Show ticket */ hesk_process_messages($hesklang['twu'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS'); @@ -476,13 +509,26 @@ if (($can_reply || $can_edit) && isset($_POST['childTrackingId'])) { } hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` SET `parent` = ' . intval($ticket['id']) . ' WHERE `trackid` = \'' . hesk_dbEscape(hesk_POST('childTrackingId')) . '\''); + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_linked_ticket', hesk_date(), + array( + 0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => hesk_POST('childTrackingId') + )); hesk_process_messages(sprintf($hesklang['link_added'], $_POST['childTrackingId']), 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS'); } /* Delete child action */ if (($can_reply || $can_edit) && isset($_GET['deleteChild'])) { //-- Delete the relationship + $innerTrackingRs = hesk_dbQuery("SELECT `trackid` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `id` = " . hesk_dbEscape($_GET['deleteChild'])); + $innerTrackingId = hesk_dbFetchAssoc($innerTrackingRs); + hesk_dbQuery('UPDATE `' . hesk_dbEscape($hesk_settings['db_pfix']) . 'tickets` SET `parent` = NULL WHERE `ID` = ' . hesk_dbEscape($_GET['deleteChild'])); + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_unlinked_ticket', hesk_date(), + array( + 0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => $innerTrackingId['trackid'] + )); hesk_process_messages($hesklang['ticket_no_longer_linked'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS'); } elseif (($can_reply || $can_edit) && isset($_GET['deleteParent'])) { @@ -528,7 +574,6 @@ if (isset($_GET['delatt']) && hesk_token_check()) { hesk_dbQuery("DELETE FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "attachments` WHERE `att_id`='" . intval($att_id) . "'"); /* Update ticket or reply in the database */ - $revision = sprintf($hesklang['thist12'], hesk_date(), $att['real_name'], $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); if ($reply) { hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "replies` SET `attachments`=REPLACE(`attachments`,'" . hesk_dbEscape($att_id . '#' . $att['real_name'] . '#' . $att['saved_name']) . ",','') WHERE `id`='" . intval($reply) . "'"); hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `id`='" . intval($ticket['id']) . "'"); @@ -539,6 +584,9 @@ if (isset($_GET['delatt']) && hesk_token_check()) { hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `attachments`=REPLACE(`attachments`,'" . hesk_dbEscape($att_id . '#' . $att['real_name'] . '#' . $att['saved_name']) . ",','') WHERE `id`='" . intval($ticket['id']) . "'"); hesk_dbQuery("UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `attachments`=REPLACE(`attachments`,'" . hesk_dbEscape($att_id . '#' . $att['real_name']) . ",',''), `history`=CONCAT(`history`,'" . hesk_dbEscape($revision) . "') WHERE `id`='" . intval($ticket['id']) . "'"); } + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_attachment_deleted', hesk_date(), + array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => $att['real_name'])); hesk_process_messages($hesklang['kb_att_rem'], 'admin_ticket.php?track=' . $trackingID . '&Refresh=' . mt_rand(10000, 99999), 'SUCCESS'); } @@ -1605,7 +1653,7 @@ function print_form() } // End print_form() function mfh_print_message() { - global $ticket, $hesklang, $hesk_settings, $can_ban_emails, $can_ban_ips, $trackingID, $modsForHesk_settings; + global $ticket, $hesklang, $hesk_settings, $can_ban_emails, $can_ban_ips, $can_unban_emails, $can_unban_ips, $trackingID, $modsForHesk_settings; ?>
  • @@ -1766,7 +1814,44 @@ function mfh_print_message() { function hesk_printTicketReplies() { - global $hesklang, $hesk_settings, $result, $reply; + global $hesklang, $hesk_settings, $result, $reply, $audit_records; + + // Sort replies and audit messages. They'll be in the proper order already + $combined_records = array(); + foreach ($audit_records as $audit_record) { + $audit_record['SORT_TYPE'] = 'AUDIT_RECORD'; + $combined_records[] = $audit_record; + } + while ($reply = hesk_dbFetchAssoc($result)) { + $reply['SORT_TYPE'] = 'REPLY'; + $combined_records[] = $reply; + } + + // Re-sort them so they're in order by date + usort($combined_records, function ($a, $b) { + $a_date = null; + $b_date = null; + if ($a['SORT_TYPE'] == 'REPLY') { + $a_date = strtotime($a['dt']); + } else { + $a_date = strtotime($a['date']); + } + + if ($b['SORT_TYPE'] == 'REPLY') { + $b_date = strtotime($b['dt']); + } else { + $b_date = strtotime($b['date']); + } + + if ($a_date === $b_date && $a['SORT_TYPE'] != $b['SORT_TYPE']) { + if ($a['SORT_TYPE'] != $b['SORT_TYPE']) { + return $a['SORT_TYPE'] == 'REPLY' ? -1 : 1; + } + } + + return $a_date - $b_date; + }); + echo '
    '; return $output; -} \ No newline at end of file +} + +function mfh_insert_audit_trail_record($entity_id, $entity_type, $language_key, $date, $replacement_values = array()) { + global $hesk_settings; + + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` (`entity_id`, `entity_type`, + `language_key`, `date`) VALUES (" . intval($entity_id) . ", '" . hesk_dbEscape($entity_type) . "', + '" . hesk_dbEscape($language_key) . "', '" . hesk_dbEscape($date) . "')"); + + $audit_id = hesk_dbInsertID(); + + foreach ($replacement_values as $replacement_index => $replacement_value) { + hesk_dbQuery("INSERT INTO `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail_to_replacement_values` + (`audit_trail_id`, `replacement_index`, `replacement_value`) VALUES (" . intval($audit_id) . ", + " . intval($replacement_index) . ", '" . hesk_dbEscape($replacement_value) . "')"); + } + + return $audit_id; +} + +function mfh_can_customer_change_status($status) +{ + global $hesk_settings; + + $res = hesk_dbQuery("SELECT `Closable` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "statuses` WHERE `ID` = " . intval($status)); + $row = hesk_dbFetchAssoc($res); + + return $row['Closable'] == 'yes' || $row['Closable'] == 'conly'; +} // END hesk_get_ticket_status() \ No newline at end of file diff --git a/inc/pipe_functions.inc.php b/inc/pipe_functions.inc.php index 4b92df4a..7a98f02d 100755 --- a/inc/pipe_functions.inc.php +++ b/inc/pipe_functions.inc.php @@ -269,7 +269,6 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority // Auto assign tickets if aplicable $tmpvar['owner'] = 0; - $tmpvar['history'] = $pop3 ? sprintf($hesklang['thist16'], hesk_date()) : sprintf($hesklang['thist11'], hesk_date()); $tmpvar['openedby'] = $pop3 ? -2 : -1; $autoassign_owner = hesk_autoAssignTicket($tmpvar['category']); @@ -278,7 +277,6 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority if ($autoassign_owner) { $tmpvar['owner'] = $autoassign_owner['id']; - $tmpvar['history'] .= sprintf($hesklang['thist10'], hesk_date(), $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')'); } // Custom fields will be empty as there is no reliable way of detecting them @@ -297,6 +295,13 @@ function hesk_email2ticket($results, $pop3 = 0, $set_category = 1, $set_priority // Insert ticket to database $ticket = hesk_newTicket($tmpvar); + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', ($pop3 ? 'audit_submitted_via_pop' : 'audit_submitted_via_piping'), hesk_date()); + + if ($autoassign_owner) { + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(), + array(0 => $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')')); + } + // Notify the customer if ($hesk_settings['notify_new']) { $possible_SPAM = false; diff --git a/inc/posting_functions.inc.php b/inc/posting_functions.inc.php index a2cd5221..7e81bfbf 100644 --- a/inc/posting_functions.inc.php +++ b/inc/posting_functions.inc.php @@ -115,7 +115,7 @@ function hesk_newTicket($ticket, $isVerified = true) " . hesk_dbEscape($ticket['screen_resolution_height']) . ", " . hesk_dbEscape($ticket['screen_resolution_width']) . ", {$due_date}, - '" . hesk_dbEscape($ticket['history']) . "' + '' {$custom_what} ) "); diff --git a/install/mods-for-hesk/sql/installSql.php b/install/mods-for-hesk/sql/installSql.php index 18cb6dc4..19991d8c 100644 --- a/install/mods-for-hesk/sql/installSql.php +++ b/install/mods-for-hesk/sql/installSql.php @@ -1137,9 +1137,9 @@ function execute320Scripts() { hesk_dbConnect(); executeQuery("ALTER TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "categories` - ADD COLUMN `mfh_description` VARCHAR(255)"); + ADD COLUMN `mfh_description` TEXT"); executeQuery("ALTER TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "custom_fields` - ADD COLUMN `mfh_description` VARCHAR(255)"); + ADD COLUMN `mfh_description` TEXT"); // Purge the custom field caches as we're adding a new field foreach ($hesk_settings['languages'] as $key => $value) { @@ -1147,5 +1147,17 @@ function execute320Scripts() { hesk_unlink(HESK_PATH . "cache/cf_{$language_hash}.cache.php"); } + executeQuery("CREATE TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail` ( + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `entity_id` INT NOT NULL, + `entity_type` VARCHAR(50) NOT NULL, + `language_key` VARCHAR(100) NOT NULL, + `date` TIMESTAMP NOT NULL)"); + executeQuery("CREATE TABLE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "audit_trail_to_replacement_values` ( + `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, + `audit_trail_id` INT NOT NULL, + `replacement_index` INT NOT NULL, + `replacement_value` TEXT NOT NULL)"); + updateVersion('3.2.0'); } \ No newline at end of file diff --git a/internal-api/dao/calendar_dao.php b/internal-api/dao/calendar_dao.php index 9c87e458..a3f15d98 100644 --- a/internal-api/dao/calendar_dao.php +++ b/internal-api/dao/calendar_dao.php @@ -194,12 +194,25 @@ function delete_event($id, $hesk_settings) { } function update_ticket_due_date($ticket, $hesk_settings) { + $ticket_id_rs = hesk_dbQuery("SELECT `id` FROM `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` WHERE `trackid` = '" . hesk_dbEscape($ticket['trackid']) . "'"); + $ticket_id = hesk_dbFetchAssoc($ticket_id_rs); + $due_date = 'NULL'; + $language_key = 'audit_due_date_removed'; + $audit_array = array(0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')'); if ($ticket['due_date'] != NULL) { + $audit_array = array( + 0 => $_SESSION['name'] . ' (' . $_SESSION['user'] . ')', + 1 => date('Y-m-d H:i:s', strtotime($ticket['due_date'])) + ); $due_date = "'" . date('Y-m-d H:i:s', strtotime($ticket['due_date'])) . "'"; + $language_key = 'audit_due_date_changed'; } $sql = "UPDATE `" . hesk_dbEscape($hesk_settings['db_pfix']) . "tickets` SET `due_date` = {$due_date}, `overdue_email_sent` = '0' WHERE `trackid` = '" . hesk_dbEscape($ticket['trackid']) . "'"; + mfh_insert_audit_trail_record($ticket_id['id'], 'TICKET', $language_key, hesk_date(), + $audit_array); + hesk_dbQuery($sql); } \ No newline at end of file diff --git a/language/en/text.php b/language/en/text.php index 61f0c1cd..d543ccd3 100644 --- a/language/en/text.php +++ b/language/en/text.php @@ -1146,6 +1146,7 @@ $hesklang['maxpost']='You probably tried to submit more data than this server ac // --> Ticket history log // Unless otherwise specified, first %s will be replaced with date and second with name/username +// THESE STRINGS ARE DEPRECATED AS OF MODS FOR HESK 3.2.0 $hesklang['thist1']='
  • %s | moved to category %s by %s
  • '; // %s = date, new category, user making change $hesklang['thist2']='
  • %s | assigned to %s by %s
  • '; // %s = date, assigned user, user making change $hesklang['thist3']='
  • %s | closed by %s
  • '; @@ -2188,5 +2189,31 @@ $hesklang['permission_group_colon'] = 'Permission Group:'; $hesklang['permission_group'] = 'Permission Group'; $hesklang['changing_permissions_will_reset_permission_group'] = 'Changing a user\'s categories / features will reset their permission group! Click "Discard Changes" to reset the user\'s categories / features.'; +// --> Ticket audit trail +$hesklang['audit_moved_category']='%s moved ticket to category %s'; // %s = new category, user making change, thist1 +$hesklang['audit_assigned']='%s assigned ticket to %s'; // %s = assigned user, user making change +$hesklang['audit_assigned_self'] = '%s assigned ticket to themself'; +$hesklang['audit_unassigned'] = '%s unassigned ticket'; +$hesklang['audit_closed']='%s closed ticket'; // thist3 +$hesklang['audit_automatically_closed'] ='Ticket automatically closed'; +$hesklang['audit_opened']='%s opened ticket'; // thist4 +$hesklang['audit_locked']='%s locked ticket'; // thist5 +$hesklang['audit_automatically_locked'] = 'Ticket automatically locked'; +$hesklang['audit_unlocked']='%s unlocked ticket'; // thist6 +$hesklang['audit_created']='%s created ticket'; +$hesklang['audit_priority']='%s changed priority to %s'; // %s = date,new priority, user making change, thist8 +$hesklang['audit_status']='%s changed status to %s'; // %s = date, new status, user making change, thist9 +$hesklang['audit_autoassigned']='%s automatically assigned to ticket'; //thist10 +$hesklang['audit_submitted_via_piping']='Ticket submitted via e-mail piping'; // thist11 +$hesklang['audit_attachment_deleted']='%s deleted attachment %s'; // %s = date, deleted attachment, user making change +$hesklang['audit_merged']='%s merged ticket %s with this ticket'; // %s = date, merged ticket ID, user making change, thist13 +$hesklang['audit_time_worked']='%s updated time worked to %s'; // %s = date, new time worked, user making change +$hesklang['audit_submitted_by']='%s submitted ticket'; +$hesklang['audit_submitted_via_pop']='Ticket submitted via POP3 fetching'; // thist16 +$hesklang['audit_due_date_removed'] = '%s removed due date'; +$hesklang['audit_due_date_changed'] = '%s changed due date to %s'; +$hesklang['audit_linked_ticket'] = '%s linked ticket %s to this ticket'; +$hesklang['audit_unlinked_ticket'] = '%s unlinked ticket %s'; + // DO NOT CHANGE BELOW if (!defined('IN_SCRIPT')) die('PHP syntax OK!'); diff --git a/submit_ticket.php b/submit_ticket.php index 03c710e4..06090ef6 100644 --- a/submit_ticket.php +++ b/submit_ticket.php @@ -405,13 +405,11 @@ if ($hesk_settings['kb_enable'] && $hesk_settings['kb_recommendanswers'] && isse // All good now, continue with ticket creation $tmpvar['owner'] = 0; -$tmpvar['history'] = sprintf($hesklang['thist15'], hesk_date(), $tmpvar['name']); // Auto assign tickets if aplicable $autoassign_owner = hesk_autoAssignTicket($tmpvar['category']); if ($autoassign_owner) { $tmpvar['owner'] = $autoassign_owner['id']; - $tmpvar['history'] .= sprintf($hesklang['thist10'], hesk_date(), $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')'); } // Insert attachments @@ -463,6 +461,14 @@ if ($createTicket) { //-- email has been verified, and a ticket can be created $ticket = hesk_newTicket($tmpvar); + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_submitted_by', hesk_date(), + array(0 => $tmpvar['name'])); + + if ($autoassign_owner) { + mfh_insert_audit_trail_record($ticket['id'], 'TICKET', 'audit_autoassigned', hesk_date(), + array(0 => $autoassign_owner['name'] . ' (' . $autoassign_owner['user'] . ')')); + } + // Notify the customer if ($hesk_settings['notify_new'] && $email_available) { hesk_notifyCustomer($modsForHesk_settings);