6658b47819bd7f1fd437af42fbbc8dcbd75cf70e
[freeside.git] / FS / FS / Cron / rt_tasks.pm
1 package FS::Cron::rt_tasks;
2
3 use strict;
4 use vars qw( @ISA @EXPORT_OK $DEBUG $conf );
5 use Exporter;
6 use FS::UID qw( dbh driver_name );
7 use FS::Record qw(qsearch qsearchs);
8 use FS::TicketSystem;
9 use FS::Conf;
10
11 use Date::Parse qw(str2time);
12
13 @ISA = qw( Exporter );
14 @EXPORT_OK = qw ( rt_daily );
15 $DEBUG = 0;
16
17 FS::UID->install_callback( sub {
18   eval "use FS::Conf;";
19   die $@ if $@;
20   $conf = FS::Conf->new;
21 });
22
23
24 my %void = ();
25
26 sub rt_daily {
27   my %opt = @_;
28   my @custnums = @ARGV; # ick
29
30   # RT_External installations should have their own cron scripts for this
31   my $system = $FS::TicketSystem::system;
32   return if $system ne 'RT_Internal';
33
34   FS::TicketSystem->init;
35   $DEBUG = 1 if $opt{'v'};
36   RT::Config->Set( LogToScreen => 'debug' ) if $DEBUG;
37  
38   # if -d or -y is in use, bail out.  There's no reliable way to tell RT 
39   # to use an alternate system time.
40   if ( $opt{'d'} or $opt{'y'} ) {
41     warn "Forced date options in use - RT daily tasks skipped.\n";
42     return;
43   }
44
45   my $session = FS::TicketSystem->session();
46   my $CurrentUser = $session->{'CurrentUser'}
47     or die "Failed to create RT session";
48
49   # load some modules that aren't handled in FS::TicketSystem 
50   foreach (qw(
51     Search::ActiveTicketsInQueue
52     Action::EscalatePriority
53     Action::EscalateQueue
54     Action::ScheduledResolve
55     )) {
56     eval "use RT::$_";
57     die $@ if $@;
58   }
59
60   # adapted from rt-crontool
61
62   # to make some actions work without complaining
63   %void = map { $_ => "RT::$_"->new($CurrentUser) }
64     (qw(Scrip ScripAction));
65
66   # compile actions to be run
67   my (@actions, @active_tickets);
68   my $queues = RT::Queues->new($CurrentUser);
69   $queues->UnLimit;
70   while (my $queue = $queues->Next) {
71     warn "Queue '".$queue->Name."'\n" if $DEBUG;
72     my $CurrentUser = $queue->CurrentUser;
73     my %opt = @_;
74     my $tickets = RT::Tickets->new($CurrentUser);
75     my $search = RT::Search::ActiveTicketsInQueue->new(
76       TicketsObj  => $tickets,
77       Argument    => $queue->Id,
78       CurrentUser => $CurrentUser,
79     );
80     $search->Prepare;
81     foreach my $custnum ( @custnums ) {
82       die "invalid custnum passed to rt_daily: $custnum"
83         if !$custnum =~ /^\d+$/;
84       $tickets->LimitMemberOf(
85         "freeside://freeside/cust_main/$custnum",
86         ENTRYAGGREGATOR => 'OR',
87         SUBCLAUSE => 'custnum'
88       );
89     }
90     while (my $ticket = $tickets->Next) {
91       warn 'Ticket #'.$ticket->Id()."\n" if $DEBUG;
92       my @a = task_actions($ticket);
93       push @actions, @a;
94       push @active_tickets, $ticket if @a; # avoid garbage collection
95     }
96   }
97
98   # and then commit them all
99   foreach (grep {$_} @actions) {
100     my ($val, $msg) = $_->Commit;
101     if ( $DEBUG ) {
102       if ($val) {
103         warn "Action committed: ".ref($_)." #".$_->TicketObj->Id."\n";
104       }
105       else {
106         warn "Action returned $msg: #".$_->TicketObj->Id."\n";
107       }
108     }
109   }
110   return;
111 }
112
113 sub task_actions {
114   my $ticket = shift;
115   (
116     ### escalation ###
117     $conf->exists('ticket_system-escalation') ? (
118       action($ticket, 'EscalatePriority', "CurrentTime: $^T"),
119       action($ticket, 'EscalateQueue')
120     ) : (),
121
122     ### scheduled resolve ###
123     action($ticket, 'ScheduledResolve'),
124   );
125 }
126
127 sub action {
128   my $ticket = shift;
129   my $CurrentUser = $ticket->CurrentUser;
130
131   my $action = shift;
132   my $argument = shift;
133
134   $action = "RT::Action::$action";
135   my $action_obj = $action->new(
136     TicketObj     => $ticket,
137     Argument      => $argument,
138     Scrip         => $void{'Scrip'},
139     ScripAction   => $void{'ScripAction'},
140     CurrentUser   => $CurrentUser,
141   );
142   if ( $action_obj->Prepare ) {
143     warn "Action prepared: $action\n" if $DEBUG;
144     return $action_obj;
145   }
146   else {
147     return;
148   }
149 }
150
151 1;