Skip to content

Commit

Permalink
Ticketing updates - guest view & resolved vs closed
Browse files Browse the repository at this point in the history
- Swap autclose for resolved to allow temporarily re-opening resolved tickets for 72 hrs after closure
- Add guest view URL for tickets
  • Loading branch information
wrongecho committed Aug 17, 2024
1 parent d931623 commit d80334a
Show file tree
Hide file tree
Showing 24 changed files with 738 additions and 204 deletions.
16 changes: 9 additions & 7 deletions client_tickets.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@

if (isset($_GET['status']) && ($_GET['status']) == 'Closed') {
$status = 'Closed';
$ticket_status_snippet = "ticket_closed_at IS NOT NULL";
$ticket_status_snippet = "ticket_resolved_at IS NOT NULL";
} else {
// Default - Show open tickets
$status = 'Open';
$ticket_status_snippet = "ticket_closed_at IS NULL";
$ticket_status_snippet = "ticket_resolved_at IS NULL";
}

if (isset($_GET['billable']) && ($_GET['billable']) == '1') {
Expand Down Expand Up @@ -49,12 +49,12 @@
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));

//Get Total tickets open
$sql_total_tickets_open = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS total_tickets_open FROM tickets WHERE ticket_client_id = $client_id AND ticket_closed_at IS NULL");
$sql_total_tickets_open = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS total_tickets_open FROM tickets WHERE ticket_client_id = $client_id AND ticket_resolved_at IS NULL");
$row = mysqli_fetch_array($sql_total_tickets_open);
$total_tickets_open = intval($row['total_tickets_open']);

//Get Total tickets closed
$sql_total_tickets_closed = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS total_tickets_closed FROM tickets WHERE ticket_client_id = $client_id AND ticket_closed_at IS NOT NULL");
$sql_total_tickets_closed = mysqli_query($mysqli, "SELECT COUNT(ticket_id) AS total_tickets_closed FROM tickets WHERE ticket_client_id = $client_id AND ticket_resolved_at IS NOT NULL");
$row = mysqli_fetch_array($sql_total_tickets_closed);
$total_tickets_closed = intval($row['total_tickets_closed']);

Expand Down Expand Up @@ -215,7 +215,7 @@

?>

<tr class="<?php if(empty($ticket_reply_created_at)) { echo "text-bold"; }?> <?php if ($ticket_reply_type == "Client") { echo "table-warning"; } ?>">
<tr class="<?php if(empty($ticket_reply_created_at)) { echo "text-bold"; }?> <?php if (empty($ticket_closed_at) && $ticket_reply_type == "Client") { echo "table-warning"; } ?>">

<!-- Ticket Number -->
<td>
Expand Down Expand Up @@ -263,8 +263,10 @@

<!-- Ticket Last Response -->
<td>
<div title="<?php echo $ticket_reply_created_at; ?>"><?php echo $ticket_reply_created_at_time_ago; ?></div>
<div><?php echo $ticket_reply_by_display; ?></div>
<?php if (!empty($ticket_reply_created_at)) { ?>
<div title="<?php echo $ticket_reply_created_at; ?>"><?php echo $ticket_reply_created_at_time_ago; ?></div>
<div><?php echo $ticket_reply_by_display; ?></div>
<?php } ?>
</td>

<!-- Ticket Created At -->
Expand Down
95 changes: 20 additions & 75 deletions cron.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
$config_ticket_from_name = sanitizeInput($row['config_ticket_from_name']);
$config_ticket_from_email = sanitizeInput($row['config_ticket_from_email']);
$config_ticket_client_general_notifications = intval($row['config_ticket_client_general_notifications']);
$config_ticket_autoclose = intval($row['config_ticket_autoclose']);
$config_ticket_autoclose_hours = intval($row['config_ticket_autoclose_hours']);
$config_ticket_new_ticket_notification_email = sanitizeInput($row['config_ticket_new_ticket_notification_email']);

Expand Down Expand Up @@ -380,86 +379,32 @@
//mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Cron', log_action = 'Task', log_description = 'Cron created sent out recurring tickets'");


// AUTO CLOSE TICKET - CLOSE
// Automatically silently closes tickets 22 hrs after the last chase
// TICKET RESOLUTION/CLOSURE PROCESS
// Changes tickets status from 'Resolved' >> 'Closed' after a defined interval

// Check to make sure auto-close is enabled
if ($config_ticket_autoclose == 1) {
$sql_tickets_to_chase = mysqli_query(
$mysqli,
"SELECT * FROM tickets
WHERE ticket_status = 4
AND ticket_updated_at < NOW() - INTERVAL $config_ticket_autoclose_hours HOUR"
);

while ($row = mysqli_fetch_array($sql_tickets_to_chase)) {

$ticket_id = $row['ticket_id'];
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_status = sanitizeInput($row['ticket_status']);
$ticket_assigned_to = sanitizeInput($row['ticket_assigned_to']);
$client_id = intval($row['ticket_client_id']);

mysqli_query($mysqli,"UPDATE tickets SET ticket_status = 5, ticket_closed_at = NOW(), ticket_closed_by = $ticket_assigned_to WHERE ticket_id = $ticket_id");

//Logging
mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Ticket', log_action = 'Closed', log_description = '$ticket_prefix$ticket_number auto closed', log_entity_id = $ticket_id");

}


// AUTO CLOSE TICKETS - CHASE
// Automatically sends a chaser email after approx 48 hrs/2 days
$sql_tickets_to_chase = mysqli_query(
$mysqli,
"SELECT contact_name, contact_email, ticket_id, ticket_prefix, ticket_number, ticket_subject, ticket_status, ticket_client_id FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
WHERE ticket_status = 4
AND ticket_updated_at < NOW() - INTERVAL 48 HOUR"
);

while ($row = mysqli_fetch_array($sql_tickets_to_chase)) {
$sql_resolved_tickets_to_close = mysqli_query(
$mysqli,
"SELECT * FROM tickets
WHERE ticket_status = 4
AND ticket_updated_at < NOW() - INTERVAL $config_ticket_autoclose_hours HOUR"
);

$contact_name = sanitizeInput($row['contact_name']);
$contact_email = sanitizeInput($row['contact_email']);
$ticket_id = intval($row['ticket_id']);
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_status = sanitizeInput( getTicketStatusName($row['ticket_status']));
$client_id = intval($row['ticket_client_id']);

$sql_ticket_reply = mysqli_query($mysqli, "SELECT ticket_reply FROM ticket_replies WHERE ticket_reply_type = 'Public' AND ticket_reply_ticket_id = $ticket_id ORDER BY ticket_reply_created_at DESC LIMIT 1");
$ticket_reply_row = mysqli_fetch_array($sql_ticket_reply);
$ticket_reply = $ticket_reply_row['ticket_reply'];

$subject = "Ticket pending closure - [$ticket_prefix$ticket_number] - $ticket_subject";

$body = "<i style=\'color: #808080\'>##- Please type your reply above this line -##</i><br><br>Hello, $contact_name<br><br>This is an automatic friendly reminder that your ticket regarding \"$ticket_subject\" will be closed, unless you respond.<br><br>--------------------------------<br>$ticket_reply--------------------------------<br><br>If your issue is resolved, you can ignore this email - the ticket will automatically close. If you need further assistance, please respond to this email. <br><br>Ticket: $ticket_prefix$ticket_number<br>Subject: $ticket_subject<br>Status: $ticket_status <br>Portal: https://$config_base_url/portal/ticket.php?id=$ticket_id<br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
while ($row = mysqli_fetch_array($sql_resolved_tickets_to_close)) {

$data = [
[
'from' => $config_ticket_from_email,
'from_name' => $config_ticket_from_name,
'recipient' => $contact_email,
'recipient_name' => $contact_name,
'subject' => $subject,
'body' => $body
]
];
$mail = addToMailQueue($mysqli, $data);
$ticket_id = $row['ticket_id'];
$ticket_prefix = sanitizeInput($row['ticket_prefix']);
$ticket_number = intval($row['ticket_number']);
$ticket_subject = sanitizeInput($row['ticket_subject']);
$ticket_status = sanitizeInput($row['ticket_status']);
$ticket_assigned_to = sanitizeInput($row['ticket_assigned_to']);
$client_id = intval($row['ticket_client_id']);

if ($mail !== true) {
mysqli_query($mysqli,"INSERT INTO notifications SET notification_type = 'Mail', notification = 'Failed to send email to $contact_email'");
mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Mail', log_action = 'Error', log_description = 'Failed to send email to $contact_email regarding $subject. $mail'");
}
mysqli_query($mysqli,"UPDATE tickets SET ticket_status = 5, ticket_closed_at = NOW(), ticket_closed_by = $ticket_assigned_to WHERE ticket_id = $ticket_id");

mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Ticket Reply', log_action = 'Create', log_description = 'Auto close chaser email sent to $contact_email for ticket $ticket_prefix$ticket_number - $ticket_subject', log_client_id = $client_id");
//Logging
mysqli_query($mysqli,"INSERT INTO logs SET log_type = 'Ticket', log_action = 'Closed', log_description = '$ticket_prefix$ticket_number auto closed', log_entity_id = $ticket_id");

}
//TODO: Add client notifs if $config_ticket_client_general_notifications is on
}

if ($config_send_invoice_reminders == 1) {
Expand Down
9 changes: 6 additions & 3 deletions cron_ticket_email_parser.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,10 @@ function addTicket($contact_id, $contact_name, $contact_email, $client_id, $date
$contact_email_esc = mysqli_real_escape_string($mysqli, $contact_email);
$client_id_esc = intval($client_id);

mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$ticket_prefix_esc', ticket_number = $ticket_number, ticket_subject = '$subject_esc', ticket_details = '$message_esc', ticket_priority = 'Low', ticket_status = 1, ticket_created_by = 0, ticket_contact_id = $contact_id, ticket_client_id = $client_id_esc");
//Generate a unique URL key for clients to access
$url_key = randomString(156);

mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$ticket_prefix_esc', ticket_number = $ticket_number, ticket_subject = '$subject_esc', ticket_details = '$message_esc', ticket_priority = 'Low', ticket_status = 1, ticket_created_by = 0, ticket_contact_id = $contact_id, ticket_url_key = '$url_key', ticket_client_id = $client_id_esc");
$id = mysqli_insert_id($mysqli);

echo "Created new ticket.<br>";
Expand Down Expand Up @@ -213,7 +216,7 @@ function addReply($from_email, $date, $subject, $ticket_number, $message, $attac
mysqli_query($mysqli, "INSERT INTO notifications SET notification_type = 'Ticket', notification = 'Email parser: $from_email attempted to re-open ticket $config_ticket_prefix_esc$ticket_number_esc (ID $ticket_id_esc) - check inbox manually to see email', notification_action = 'ticket.php?ticket_id=$ticket_id_esc', notification_client_id = $client_id_esc");

$email_subject = "Action required: This ticket is already closed";
$email_body = "Hi there, <br><br>You've tried to reply to a ticket that is closed - we won't see your response. <br><br>Please raise a new ticket by sending a fresh e-mail to our support address below. <br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
$email_body = "Hi there, <br><br>You've tried to reply to a ticket that is closed - we won't see your response. <br><br>Please raise a new ticket by sending a new e-mail to our support address below. <br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";

$data = [
[
Expand Down Expand Up @@ -301,7 +304,7 @@ function addReply($from_email, $date, $subject, $ticket_number, $message, $attac
}
}

mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 2 WHERE ticket_id = $ticket_id AND ticket_client_id = $client_id LIMIT 1");
mysqli_query($mysqli, "UPDATE tickets SET ticket_status = 2, ticket_resolved_at = NULL WHERE ticket_id = $ticket_id AND ticket_client_id = $client_id LIMIT 1");

echo "Updated existing ticket.<br>";
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Ticket', log_action = 'Update', log_description = 'Email parser: Client contact $from_email_esc updated ticket $config_ticket_prefix$ticket_number_esc ($subject)', log_client_id = $client_id");
Expand Down
50 changes: 43 additions & 7 deletions database_updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -2084,16 +2084,52 @@
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.4.2'");
}

// if (CURRENT_DATABASE_VERSION == '1.4.2') {
mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_ticket_email_parse_unknown_senders` INT(1) NOT NULL DEFAULT '0' AFTER `config_ticket_email_parse`");
if (CURRENT_DATABASE_VERSION == '1.4.2') {
mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_ticket_email_parse_unknown_senders` INT(1) NOT NULL DEFAULT '0' AFTER `config_ticket_email_parse`");

mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.4.3'");
// }
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.4.3'");
}

if (CURRENT_DATABASE_VERSION == '1.4.3') {

// Add ticket URL key column
mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_url_key` VARCHAR(200) DEFAULT NULL AFTER `ticket_feedback`");
// Populate pre-existing columns for open tickets
$sql_tickets_1 = mysqli_query($mysqli, "SELECT ticket_id FROM tickets WHERE tickets.ticket_closed_at IS NULL");
foreach ($sql_tickets_1 as $row) {
$ticket_id = intval($row['ticket_id']);
$url_key = randomString(156);
mysqli_query($mysqli, "UPDATE tickets SET ticket_url_key = '$url_key' WHERE ticket_id = '$ticket_id'");
}

// Add ticket resolved at column
mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_resolved_at` DATETIME DEFAULT NULL AFTER `ticket_updated_at`");
// Populate pre-existing columns for closed tickets
$sql_tickets_2 = mysqli_query($mysqli, "SELECT ticket_id, ticket_updated_at, ticket_closed_at FROM tickets WHERE tickets.ticket_closed_at IS NOT NULL");
foreach ($sql_tickets_2 as $row) {
$ticket_id = intval($row['ticket_id']);
$ticket_updated_at = sanitizeInput($row['ticket_updated_at']); // To keep old updated_at time
$ticket_closed_at = sanitizeInput($row['ticket_closed_at']);
mysqli_query($mysqli, "UPDATE tickets SET ticket_resolved_at = '$ticket_closed_at', ticket_updated_at = '$ticket_updated_at' WHERE ticket_id = '$ticket_id'");
}

// Change ticket status 'Auto close' to 'Resolved'
mysqli_query($mysqli, "UPDATE `ticket_statuses` SET `ticket_status_name` = 'Resolved' WHERE `ticket_statuses`.`ticket_status_id` = 4");

// Auto-close is no longer optional
mysqli_query($mysqli, "ALTER TABLE `settings` DROP `config_ticket_autoclose`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_ticket_autoclose_hours` = '72'");

// DB Version
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.4.4'");


}

// if (CURRENT_DATABASE_VERSION == '1.4.3') {
// // Insert queries here required to update to DB version 1.4.4
// if (CURRENT_DATABASE_VERSION == '1.4.4') {
// // Insert queries here required to update to DB version 1.4.5
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.4.4'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '1.4.5'");
// }

} else {
Expand Down
2 changes: 1 addition & 1 deletion database_version.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
* It is used in conjunction with database_updates.php
*/

DEFINE("LATEST_DATABASE_VERSION", "1.4.3");
DEFINE("LATEST_DATABASE_VERSION", "1.4.4");
3 changes: 2 additions & 1 deletion db.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1469,7 +1469,6 @@ CREATE TABLE `settings` (
`config_ticket_email_parse` tinyint(1) NOT NULL DEFAULT 0,
`config_ticket_email_parse_unknown_senders` tinyint(1) NOT NULL DEFAULT 0,
`config_ticket_client_general_notifications` tinyint(1) NOT NULL DEFAULT 1,
`config_ticket_autoclose` tinyint(1) NOT NULL DEFAULT 0,
`config_ticket_autoclose_hours` int(5) NOT NULL DEFAULT 72,
`config_ticket_new_ticket_notification_email` varchar(200) DEFAULT NULL,
`config_ticket_default_billable` tinyint(1) NOT NULL DEFAULT 0,
Expand Down Expand Up @@ -1846,8 +1845,10 @@ CREATE TABLE `tickets` (
`ticket_onsite` tinyint(1) NOT NULL DEFAULT 0,
`ticket_vendor_ticket_number` varchar(255) DEFAULT NULL,
`ticket_feedback` varchar(200) DEFAULT NULL,
`ticket_url_key` varchar(200) DEFAULT NULL,
`ticket_created_at` datetime NOT NULL DEFAULT current_timestamp(),
`ticket_updated_at` datetime DEFAULT NULL ON UPDATE current_timestamp(),
`ticket_resolved_at` datetime DEFAULT NULL,
`ticket_archived_at` datetime DEFAULT NULL,
`ticket_closed_at` datetime DEFAULT NULL,
`ticket_created_by` int(11) NOT NULL,
Expand Down
4 changes: 4 additions & 0 deletions functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,10 @@ function sanitizeForEmail($data)

function timeAgo($datetime)
{
if (is_null($datetime)) {
return "-";
}

$time = strtotime($datetime);
$difference = $time - time(); // Changed to handle future dates

Expand Down
1 change: 0 additions & 1 deletion get_settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@
$config_ticket_email_parse = intval($row['config_ticket_email_parse']);
$config_ticket_email_parse_unknown_senders = intval($row['config_ticket_email_parse_unknown_senders']);
$config_ticket_client_general_notifications = intval($row['config_ticket_client_general_notifications']);
$config_ticket_autoclose = intval($row['config_ticket_autoclose']);
$config_ticket_autoclose_hours = intval($row['config_ticket_autoclose_hours']);
$config_ticket_new_ticket_notification_email = $row['config_ticket_new_ticket_notification_email'];
$config_ticket_default_billable = intval($row['config_ticket_default_billable']);
Expand Down
Loading

0 comments on commit d80334a

Please sign in to comment.