Merge branch 'master' of git.freeside.biz:/home/git/freeside
[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 !defined($system) || $system ne 'RT_Internal';
33
34   system('/opt/rt3/sbin/rt-fulltext-indexer --quiet --limit 5400 &');
35
36   # if -d or -y is in use, bail out.  There's no reliable way to tell RT 
37   # to use an alternate system time.
38   if ( $opt{'d'} or $opt{'y'} ) {
39     warn "Forced date options in use - RT daily tasks skipped.\n";
40     return;
41   }
42
43   FS::TicketSystem->init;
44   my $session = FS::TicketSystem->session();
45   my $CurrentUser = $session->{'CurrentUser'}
46     or die "Failed to create RT session";
47
48   $DEBUG = 1 if $opt{'v'};
49   RT::Config->Set( LogToScreen => 'debug' ) if $DEBUG;
50  
51   # load some modules that aren't handled in FS::TicketSystem 
52   foreach (qw(
53     Search::ActiveTicketsInQueue
54     Action::EscalatePriority
55     Action::EscalateQueue
56     Action::ScheduledResolve
57     )) {
58     eval "use RT::$_";
59     die $@ if $@;
60   }
61
62   # adapted from rt-crontool
63
64   # to make some actions work without complaining
65   %void = map { $_ => "RT::$_"->new($CurrentUser) }
66     (qw(Scrip ScripAction));
67
68   # compile actions to be run
69   my (@actions, @active_tickets);
70   my $queues = RT::Queues->new($CurrentUser);
71   $queues->UnLimit;
72   while (my $queue = $queues->Next) {
73     warn "Queue '".$queue->Name."'\n" if $DEBUG;
74     my %opt = @_;
75     my $tickets = RT::Tickets->new($CurrentUser);
76     my $search = RT::Search::ActiveTicketsInQueue->new(
77       TicketsObj  => $tickets,
78       Argument    => $queue->Id,
79       CurrentUser => $CurrentUser,
80     );
81     $search->Prepare;
82     foreach my $custnum ( @custnums ) {
83       die "invalid custnum passed to rt_daily: $custnum"
84         if !$custnum =~ /^\d+$/;
85       $tickets->LimitMemberOf(
86         "freeside://freeside/cust_main/$custnum",
87         ENTRYAGGREGATOR => 'OR',
88         SUBCLAUSE => 'custnum'
89       );
90     }
91     while (my $ticket = $tickets->Next) {
92       warn 'Ticket #'.$ticket->Id()."\n" if $DEBUG;
93       my @a = task_actions($ticket);
94       push @actions, @a;
95       push @active_tickets, $ticket if @a; # avoid garbage collection
96     }
97   }
98
99   # and then commit them all
100   foreach (grep {$_} @actions) {
101     my ($val, $msg) = $_->Commit;
102     if ( $DEBUG ) {
103       if ($val) {
104         warn "Action committed: ".ref($_)." #".$_->TicketObj->Id."\n";
105       }
106       else {
107         warn "Action returned $msg: #".$_->TicketObj->Id."\n";
108       }
109     }
110   }
111   return;
112 }
113
114 sub task_actions {
115   my $ticket = shift;
116   (
117     ### escalation ###
118     $conf->exists('ticket_system-escalation') ? (
119       action($ticket, 'EscalatePriority', "CurrentTime: $^T"),
120       action($ticket, 'EscalateQueue')
121     ) : (),
122
123     ### scheduled resolve ###
124     action($ticket, 'ScheduledResolve'),
125   );
126 }
127
128 sub action {
129   my $ticket = shift;
130   my $CurrentUser = $ticket->CurrentUser;
131
132   my $action = shift;
133   my $argument = shift;
134
135   $action = "RT::Action::$action";
136   my $action_obj = $action->new(
137     TicketObj     => $ticket,
138     Argument      => $argument,
139     Scrip         => $void{'Scrip'},
140     ScripAction   => $void{'ScripAction'},
141     CurrentUser   => $CurrentUser,
142   );
143   if ( $action_obj->Prepare ) {
144     warn "Action prepared: $action\n" if $DEBUG;
145     return $action_obj;
146   }
147   else {
148     return;
149   }
150 }
151
152 1;