4977eb2f8be8b6d6547895e0c93d76f44184fd49
[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   $DEBUG = 1 if $opt{'v'};
35   RT::Config->Set( LogToScreen => 'debug' ) if $DEBUG;
36  
37   # if -d or -y is in use, bail out.  There's no reliable way to tell RT 
38   # to use an alternate system time.
39   if ( $opt{'d'} or $opt{'y'} ) {
40     warn "Forced date options in use - RT daily tasks skipped.\n";
41     return;
42   }
43
44   FS::TicketSystem->init;
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 %opt = @_;
73     my $tickets = RT::Tickets->new($CurrentUser);
74     my $search = RT::Search::ActiveTicketsInQueue->new(
75       TicketsObj  => $tickets,
76       Argument    => $queue->Id,
77       CurrentUser => $CurrentUser,
78     );
79     $search->Prepare;
80     foreach my $custnum ( @custnums ) {
81       die "invalid custnum passed to rt_daily: $custnum"
82         if !$custnum =~ /^\d+$/;
83       $tickets->LimitMemberOf(
84         "freeside://freeside/cust_main/$custnum",
85         ENTRYAGGREGATOR => 'OR',
86         SUBCLAUSE => 'custnum'
87       );
88     }
89     while (my $ticket = $tickets->Next) {
90       warn 'Ticket #'.$ticket->Id()."\n" if $DEBUG;
91       my @a = task_actions($ticket);
92       push @actions, @a;
93       push @active_tickets, $ticket if @a; # avoid garbage collection
94     }
95   }
96
97   # and then commit them all
98   foreach (grep {$_} @actions) {
99     my ($val, $msg) = $_->Commit;
100     if ( $DEBUG ) {
101       if ($val) {
102         warn "Action committed: ".ref($_)." #".$_->TicketObj->Id."\n";
103       }
104       else {
105         warn "Action returned $msg: #".$_->TicketObj->Id."\n";
106       }
107     }
108   }
109   return;
110 }
111
112 sub task_actions {
113   my $ticket = shift;
114   (
115     ### escalation ###
116     $conf->exists('ticket_system-escalation') ? (
117       action($ticket, 'EscalatePriority', "CurrentTime: $^T"),
118       action($ticket, 'EscalateQueue')
119     ) : (),
120
121     ### scheduled resolve ###
122     action($ticket, 'ScheduledResolve'),
123   );
124 }
125
126 sub action {
127   my $ticket = shift;
128   my $CurrentUser = $ticket->CurrentUser;
129
130   my $action = shift;
131   my $argument = shift;
132
133   $action = "RT::Action::$action";
134   my $action_obj = $action->new(
135     TicketObj     => $ticket,
136     Argument      => $argument,
137     Scrip         => $void{'Scrip'},
138     ScripAction   => $void{'ScripAction'},
139     CurrentUser   => $CurrentUser,
140   );
141   if ( $action_obj->Prepare ) {
142     warn "Action prepared: $action\n" if $DEBUG;
143     return $action_obj;
144   }
145   else {
146     return;
147   }
148 }
149
150 1;