Rt-askForFeedback

From Request Tracker Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Installation

1. Create a Global "Custom Field" with the Name: "Reminder4Stalled".
2. Place this script somewhere on a server:

#!/usr/bin/perl -w

 # This Script bases on:
 # http://requesttracker.wikia.com/wiki/RtUnifiedreminder
 
 ###############################################
 ### Author: Pascal Wagenhofer / Q-X GmbH, Switzerland
 ### Email: wagenhofer@q-x.ch
 ### Date: 07/15/2013
 ###############################################
 ### This script is provided "as it is" and comes without any warranty. Use it, modify
 ### it or do whatever you want with it.
 ###############################################
 ### Feedback is always welcome at wagenhofer@q-x.ch
 ###############################################
 
 ### INSTALLATION ###
 ### Read http://requesttracker.wikia.com/wiki/Rt-askForFeedback
 
 # RT3 reminder script
 # One big reminder report about ALL tickets that are getting to be too long since LastUpdated
 # Sends multipart HTML + plaintext email, so HTML capable mail readers can click links
 # Many pieces cannibalized from the other reminder scripts in the wiki.
 
 # You will run this script from cron as a user with perms to read the RT_SiteConfig.pm config file
 # Crontab would look like this to run twice a day, at 10:15am and 3:15pm
 ## send unified remind email twice per day
 #15 10 * * * /home/crystalfontz/scripts/rt_reminder2cust.pl
 
 # This Script bases on:
 # http://requesttracker.wikia.com/wiki/RtUnifiedreminder
 
 ### Configuration
 
 # Location of RT3's libs -- Change this to where yours are
 use lib ("/usr/share/request-tracker3.8/lib", "/usr/local/share/request-tracker3.8/lib", "/usr/local/rt/lib");
 
 # Address emails should originate from
 my($from) = 'Ticket Sys ';
 
 # maximum number of seconds since LastUpdated, beyond which the ticket will be reported
 my %max_untouched_ages = (
                           "stalled" => 60 * 60 * 24 * 3,  # 3 days before warn about stalled
                           "2beclosed" => 60 * 60 * 24 * 3,  # 3 days before warn about stalled
                          );
 
 # Queues to operate on. Default is all
 # my @goodqueues = qw[ThisQueue ThatQueue]; # to look only in specific queues, uncomment this line and comment the next one
 my @goodqueues = (); # leave like this to look in all queues
 
 # Queues to skip. Default is none. Use either @goodqueues or @badqueues, not both.
 # my @badqueues = qw[ ]; # If you have no queues to exclude, uncomment this line and comment the next one
 #my @badqueues = qw[Ignoreme IgnoreAnother]; # To exclude certain queues, list them here and comment line above
 
 my($debug) = 0; # nonzero will print plaintext report to STOUT instead of emailing it
 
 # The length at which lines for plaintext mail will be truncated. 78, or thereabouts looks
 # best for most people. Setting to 0 will stop lines being truncated.
 my($linelen) = 78; # has no effect on HTML mail
 
 #Enter here the path/url for the REST-API of Request Tracker
 my($apiurl) = "https://your.url.tld/rt3/REST/1.0/";
 my($username) = "username"; #Username to access RT3 (needs to have rights to update CF in the appropriate Queue(s)
 my($password) = "password"; #Password of the above username
 my($agentname) = "Your LWP::Agent-Name";
 
 #Mail-Section
 my $plainbody = "your Body of the E-Mail (Plaintext)";
 my $subjectline = "Your subject of the e-mail to the customer"; #Example: "[TicketSys #$ticketNumber] $subject"
 
 
 ### Code
 
 use strict;
 use Carp;
 use MIME::Lite;
 use URI::Escape;
 use LWP;
 
 # Pull in the RT stuff
 package RT;
 use RT::Interface::CLI qw(CleanEnv GetCurrentUser GetMessageContent loc);
 
 CleanEnv();       # Clean our the environment
 RT::LoadConfig(); # Load the RT configuration
 RT::Init();       # Initialise RT
 
 use RT::Date;
 use RT::Queue;
 use RT::Queues;
 use RT::Tickets;

 my $max_age = 0;

 my $user = new RT::User($RT::SystemUser); # Define an RT User variable
 my $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results
 my $date = new RT::Date($RT::SystemUser); # Define a date variable (used for comparisions)
 my $now = new RT::Date($RT::SystemUser); # get current time
 $now->SetToNow();
 
 # Limit the ticket search to new and open only.
 $tickets->LimitCustomField(
	CUSTOMFIELD => 'Reminder4Stalled',
		OPERATOR => '!=',
		VALUE => '1'
 );
 $tickets->LimitStatus(VALUE => 'stalled');
 
 my $searchqueue = ;
 
 if($#goodqueues != -1)
 {
     $tickets->_OpenParen();
     foreach my $queue (@goodqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '=');
     }
     $tickets->_CloseParen();
     $searchqueue = " AND (Queue = '". join("' OR Queue = '", @goodqueues) ."')";
 }
 elsif($#badqueues != -1)
 {
     foreach my $queue (@badqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '!=');
     }
     $searchqueue = " AND Queue != '". join("' AND Queue != '", @badqueues) ."'";
 }

 $tickets->OrderByCols( {FIELD => 'Status', ORDER => 'ASC'},
                        {FIELD => 'queue', ORDER => 'ASC'},
                        {FIELD => 'Priority', ORDER => 'DESC'},
                        {FIELD => 'LastUpdated', ORDER => 'ASC'},
                       );

 # We might not want to print the message if there are no tickets
 my($printmsg) = 0;

 my $j = 0;
 my $bgcolor = ;
 my $last_status = ;
 my $status_title = ;
 my $count_by_status = 0;
 my $searchURL = ;

 # Loop through tickets for reminder
 while (my $Ticket = $tickets->Next)
 {
     # Compare Dates to see if LastUpdated date is old enough to report
     $max_age = $max_untouched_ages{$Ticket->Status} || 0;
     my $max_age_2resolve = $max_untouched_ages{'2beclosed'} || 0;
 
     $date->Set(Format => "ISO", Value => $Ticket->LastUpdated);
     if ($now->Unix - $date->Unix < $max_age) { next; } # skip it if too young
     $j++;
 
     $user->Load($Ticket->Owner);
     
	use LWP;
	my $ua = LWP::UserAgent->new;
	$ua->timeout(10);
	$ua->agent($agentname);
	my $uri = $apiurl;
	my $access_user = $username;
	my $access_password = $password;
	my $ticketNumber = $Ticket->{values}->{'id'};
	my @customermail = "";

     my $response = $ua->post($uri."ticket/$ticketNumber/edit",
   ['user' => $access_user, 'pass' => $access_password,
    'content' => 'CF.{Reminder4Stalled}: 1']);
    
    if ($response->is_success) {
 
     if($Ticket->Status ne $last_status)
     { 
         $last_status = $Ticket->Status;
 
         $count_by_status = 0; # reset on every difft status

         # get a date object that can give us the datetime cutoff for this query
         $date->SetToNow();
     }
 
     # Use our own date formatting routine
     my($updated) = &formatDate($Ticket->LastUpdatedObj->Unix);
     my($subject) = $Ticket->Subject ? $Ticket->Subject : "(No subject)";
     my($queue) = substr($Ticket->QueueObj->Name, 0, 7);
 
     my($line) = sprintf "%5d  %-7s %3d  %-13s %-7s %-6s %-30s",
                          $Ticket->Id, $Ticket->Status, $Ticket->Priority, $updated, $queue, $user->Name, $subject;
 
     # Truncate lines if required
     if($linelen)
     {
         $line = substr($line, 0, $linelen);
     }
     
     # ---- GET ALL REQUESTORS
	my $response = $ua->post($uri."ticket/$ticketNumber",
	['user' => $access_user, 'pass' => $access_password]);

	if ($response->is_success) {
	my $html = $response->decoded_content;
	my @array1=split(/\n/,$html);
	my @array2=split(/Requestors: (.*)/,$array1[11]);
	if ($#array2 > 1) {
		@customermail=split(m/\ (.*)/,$array2[1]);
	} else {
		@customermail=$array2[1];
	}
	
	# ----- END GET ALL REQUESTORS

	my $receiviers = "";
	my $sendto = $array2[1];
	
	my $subjecttot = $subjectline;
	
	my $msg = MIME::Lite->new(From    => $from,
                           To      =>  join(',', $sendto),
                           Subject => $subjecttot,
                           Type    => 'text/plain',
                           Charset    => 'utf8',
			   Data	=> $plainbody);
 
     if ($debug)
     {
	 print "Would send E-Mail for Ticket #".$ticketNumber."\n";
     }
     else
     {
	$msg->send;
     }
     }
 }
}

 $tickets = new RT::Tickets($RT::SystemUser); # Used to store Ticket search results
 $tickets->LimitCustomField(
	CUSTOMFIELD => 'Reminder4Stalled',
		OPERATOR => '=',
		VALUE => '1'
 );
$searchqueue = ;
 
 if($#goodqueues != -1)
 {
     $tickets->_OpenParen();
     foreach my $queue (@goodqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '=');
     }
     $tickets->_CloseParen();
     $searchqueue = " AND (Queue = '". join("' OR Queue = '", @goodqueues) ."')";
 }
 elsif($#badqueues != -1)
 {
     foreach my $queue (@badqueues)
     {
         $tickets->LimitQueue(VALUE => $queue, OPERATOR => '!=');
     }
     $searchqueue = " AND Queue != '". join("' AND Queue != '", @badqueues) ."'";
 }

 $tickets->OrderByCols( {FIELD => 'Status', ORDER => 'ASC'},
                        {FIELD => 'queue', ORDER => 'ASC'},
                        {FIELD => 'Priority', ORDER => 'DESC'},
                        {FIELD => 'LastUpdated', ORDER => 'ASC'},
                       );

 # We might not want to print the message if there are no tickets
($printmsg) = 0;

$j = 0;
$bgcolor = ;
$last_status = ;
$status_title = ;
$count_by_status = 0;
$searchURL = ;

# Loop through tickets to close
 while (my $Ticket = $tickets->Next)
 {
     # Compare Dates to see if LastUpdated date is old enough to report
     $max_age = $max_untouched_ages{$Ticket->Status} || 0;
     my $max_age_2resolve = $max_untouched_ages{'2beclosed'} || 0;
 
     $date->Set(Format => "ISO", Value => $Ticket->LastUpdated);
     if ($now->Unix - $date->Unix < $max_age_2resolve) { next; } # skip it if too young
     $j++;
 
     $user->Load($Ticket->Owner);

     if($Ticket->Status ne $last_status)
     { 
         $last_status = $Ticket->Status;
 
         $count_by_status = 0; # reset on every difft status
 
         # get a date object that can give us the datetime cutoff for this query
         $date->SetToNow();
     }
 
     # Use our own date formatting routine
     my ($updated) = &formatDate($Ticket->LastUpdatedObj->Unix);
     my ($subject) = $Ticket->Subject ? $Ticket->Subject : "(No subject)";
     my ($queue) = substr($Ticket->QueueObj->Name, 0, 7);
 
     my ($line) = sprintf "%5d  %-7s %3d  %-13s %-7s %-6s %-30s",
                          $Ticket->Id, $Ticket->Status, $Ticket->Priority, $updated, $queue, $user->Name, $subject;
			  
     if ($debug)
     {
	 print "Would close Ticket ".$Ticket->Id."\n\n";
     }
     else
     {
	  $Ticket->Resolve();
     }
}

 
 # Disconnect before we finish off
 $RT::Handle->Disconnect();
 exit 0;
 
 # Formats a date like: Thu 10-07-03
 # Designed to be consice yet useful
 sub formatDate() {
     my($unixtime) = @_;
     my(@days) = ( "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" );
     # Return an empty string if we haven't been given a time
     return "" if $unixtime <= 0;
     my($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime($unixtime);
     return sprintf "%s %02d-%02d-%02d", $days[$wday], $mon+1, $mday, $year%100;
 }

3. install a Cronjob on your server (see script head)

4. Now, we need to setup a new Scrip to reset the "Reminder4Stalled"-Field in case of Correspondance. Create a new Scrip in the Global-Section which looks like this:

Description: "Set Reminder4Stalled = 0"
Condition: "On Correspondance"
Action: "User defined"
Template: "Global Template: empty"
Phase: "TransactionCreate"

User Defined Condition:

return 1;

User Defined Action Preparation Code:

my $ticket = $self->TicketObj;
my $cf_obj = RT::CustomField->new($RT::SystemUser);
my $cf_name = "Reminder4Stalled";
my $cf_value = "0";

$cf_obj->LoadByName( Name => $cf_name );
$RT::Logger->debug( "Loaded \$cf_obj->Name = ". $cf_obj->Name() ."\n" );
$ticket->AddCustomFieldValue( Field=>$cf_obj, Value=>$cf_value,
RecordTransaction=>0 );

User Defined Post Action Code:

return 1;