ticket escalation, part 2, RT#8254
[freeside.git] / rt / lib / RT / Action / EscalateQueue.pm
1 =head1 NAME
2
3 RT::Action::EscalateQueue - move a ticket to a different queue when it reaches its final priority
4
5 =head1 DESCRIPTION
6
7 EscalateQueue is a ScripAction that will move a ticket to a new 
8 queue when its priority equals its final priority.  It is designed 
9 to be used with LinearEscalate or another action that increments
10 ticket priority on some schedule.  Like those actions, it is intended 
11 to be called from an escalation tool.
12
13 =head1 CONFIGURATION
14
15 FinalPriority is a ticket property, defaulting to the queue property.
16
17 EscalateQueue is a queue custom field using RT::CustomFieldValues::Queue 
18 as its data source (that is, it refers to another queue).  Tickets at 
19 FinalPriority will be moved to that queue.
20
21 From a shell you can use the following command:
22
23     rt-crontool --search RT::Search::FromSQL --search-arg \
24     "(Status='new' OR Status='open' OR Status = 'stalled')" \
25     --action RT::Action::EscalateQueue
26
27 No action argument is needed.  Each ticket will be escalated based on the
28 EscalateQueue property of its current queue.
29
30 =cut
31
32 package RT::Action::EscalateQueue;
33
34 use strict;
35 use warnings;
36 use base qw(RT::Action);
37
38 our $VERSION = '0.01';
39
40 #What does this type of Action does
41
42 sub Describe {
43     my $self = shift;
44     my $class = ref($self) || $self;
45     return "$class will move a ticket to its escalation queue when it reaches its final priority."
46 }
47
48 #This Prepare only returns 1 if the ticket will be escalated.
49
50 sub Prepare {
51     my $self = shift;
52
53     my $ticket = $self->TicketObj;
54     my $queue = $ticket->QueueObj;
55     my $new_queue = $queue->FirstCustomFieldValue('EscalateQueue');
56
57     my $ticketid = 'Ticket #'.$ticket->Id; #for debug messages
58     if ( $ticket->InitialPriority == $ticket->FinalPriority ) {
59         $RT::Logger->debug("$ticketid has no priority range.  Not escalating.");
60         return 0;
61     }
62
63     if ( $ticket->Priority == $ticket->FinalPriority ) {
64         if (!$new_queue) {
65             $RT::Logger->debug("$ticketid has no escalation queue.  Not escalating.");
66             return 0;
67         }
68         if ($new_queue eq $queue->Name) {
69             $RT::Logger->debug("$ticketid would be escalated to its current queue.");
70             return 0;
71         }
72         $self->{'new_queue'} = $new_queue;
73         return 1;
74     }
75     return 0;
76 }
77
78 # whereas Commit returns 1 if it succeeds at whatever it's doing
79 sub Commit {
80     my $self = shift;
81
82     return 1 if !exists($self->{'new_queue'});
83
84     my $ticket = $self->TicketObj;
85     my $ticketid = 'Ticket #'.$ticket->Id;
86     my $new_queue = RT::Queue->new($ticket->CurrentUser);
87     $new_queue->Load($self->{'new_queue'});
88     if ( ! $new_queue ) {
89         $RT::Logger->debug("Escalation queue ".$self->{'new_queue'}." not found.");
90         return 0;
91     }
92  
93     $RT::Logger->debug("Escalating $ticket from ".$ticket->QueueObj->Name .
94         ' to '.  $new_queue->Name . ', FinalPriority '.$new_queue->FinalPriority);
95
96     my ( $val, $msg ) = $ticket->SetQueue($self->{'new_queue'});
97     if (! $val) {
98         $RT::Logger->error( "Couldn't set queue: $msg" );
99         return (0, $msg);
100     }
101
102     # Set properties of the ticket according to its new queue, so that 
103     # escalation Does What You Expect.  Don't record transactions for this;
104     # the queue change should be enough.
105
106     ( $val, $msg ) = $ticket->_Set(
107       Field => 'FinalPriority',
108       Value => $new_queue->FinalPriority,
109       RecordTransaction => 0,
110     );
111     if (! $val) {
112         $RT::Logger->error( "Couldn't set new final priority: $msg" );
113         return (0, $msg);
114     }
115     my $Due = new RT::Date( $ticket->CurrentUser );
116     if ( my $due_in = $new_queue->DefaultDueIn ) {
117         $Due->SetToNow;
118         $Due->AddDays( $due_in );
119     }
120     ( $val, $msg ) = $ticket->_Set(
121       Field => 'Due',
122       Value => $Due->ISO,
123       RecordTransaction => 0,
124     );
125     if (! $val) {
126         $RT::Logger->error( "Couldn't set new due date: $msg" );
127         return (0, $msg);
128     }
129     return 1;
130 }
131
132 1;
133
134 =head1 AUTHOR
135
136 Mark Wells E<lt>mark@freeside.bizE<gt>
137
138 Based on in part LinearEscalate by Kevin Riggle E<lt>kevinr@bestpractical.comE<gt>
139 and Ruslan Zakirov E<lt>ruz@bestpractical.comE<gt> .
140
141 =cut