summaryrefslogtreecommitdiff
path: root/FS/FS/Cron/rt_tasks.pm
blob: 21488762aa406895b7ed50459f9a79ea9e6d518c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package FS::Cron::rt_tasks;

use strict;
use vars qw( @ISA @EXPORT_OK $DEBUG $conf );
use Exporter;
use FS::UID qw( dbh driver_name );
use FS::Record qw(qsearch qsearchs);
use FS::TicketSystem;
use FS::Conf;

use Date::Parse qw(str2time);

@ISA = qw( Exporter );
@EXPORT_OK = qw ( rt_daily );
$DEBUG = 0;

FS::UID->install_callback( sub {
  eval "use FS::Conf;";
  die $@ if $@;
  $conf = FS::Conf->new;
});


my %void = ();

sub rt_daily {
  my %opt = @_;
  my @custnums = @ARGV; # ick

  # RT_External installations should have their own cron scripts for this
  my $system = $FS::TicketSystem::system;
  return if !defined($system) || $system ne 'RT_Internal';

  system('/opt/rt3/sbin/rt-clean-sessions --older 1M --skip-user &');

  system('/opt/rt3/sbin/rt-fulltext-indexer --quiet --limit 5400 &');

  # if -d or -y is in use, bail out.  There's no reliable way to tell RT 
  # to use an alternate system time.
  if ( $opt{'d'} or $opt{'y'} ) {
    warn "Forced date options in use - RT daily tasks skipped.\n";
    return;
  }

  FS::TicketSystem->init;
  my $session = FS::TicketSystem->session();
  my $CurrentUser = $session->{'CurrentUser'}
    or die "Failed to create RT session";

  $DEBUG = 1 if $opt{'v'};
  RT::Config->Set( LogToScreen => 'debug' ) if $DEBUG;
 
  # load some modules that aren't handled in FS::TicketSystem 
  foreach (qw(
    Search::ActiveTicketsInQueue
    Action::EscalatePriority
    Action::EscalateQueue
    Action::ScheduledResolve
    )) {
    eval "use RT::$_";
    die $@ if $@;
  }

  # adapted from rt-crontool

  # to make some actions work without complaining
  %void = map { $_ => "RT::$_"->new($CurrentUser) }
    (qw(Scrip ScripAction));

  # compile actions to be run
  my (@actions, @active_tickets);
  my $queues = RT::Queues->new($CurrentUser);
  $queues->UnLimit;
  while (my $queue = $queues->Next) {
    warn "Queue '".$queue->Name."'\n" if $DEBUG;
    my %opt = @_;
    my $tickets = RT::Tickets->new($CurrentUser);
    my $search = RT::Search::ActiveTicketsInQueue->new(
      TicketsObj  => $tickets,
      Argument    => $queue->Id,
      CurrentUser => $CurrentUser,
    );
    $search->Prepare;
    foreach my $custnum ( @custnums ) {
      die "invalid custnum passed to rt_daily: $custnum"
        if !$custnum =~ /^\d+$/;
      $tickets->LimitMemberOf(
        "freeside://freeside/cust_main/$custnum",
        ENTRYAGGREGATOR => 'OR',
        SUBCLAUSE => 'custnum'
      );
    }
    while (my $ticket = $tickets->Next) {
      warn 'Ticket #'.$ticket->Id()."\n" if $DEBUG;
      my @a = task_actions($ticket);
      push @actions, @a;
      push @active_tickets, $ticket if @a; # avoid garbage collection
    }
  }

  # and then commit them all
  foreach (grep {$_} @actions) {
    my ($val, $msg) = $_->Commit;
    if ( $DEBUG ) {
      if ($val) {
        warn "Action committed: ".ref($_)." #".$_->TicketObj->Id."\n";
      }
      else {
        warn "Action returned $msg: #".$_->TicketObj->Id."\n";
      }
    }
  }
  return;
}

sub task_actions {
  my $ticket = shift;
  (
    ### escalation ###
    $conf->exists('ticket_system-escalation') ? (
      action($ticket, 'EscalatePriority', "CurrentTime: $^T"),
      action($ticket, 'EscalateQueue')
    ) : (),

    ### scheduled resolve ###
    action($ticket, 'ScheduledResolve'),
  );
}

sub action {
  my $ticket = shift;
  my $CurrentUser = $ticket->CurrentUser;

  my $action = shift;
  my $argument = shift;

  $action = "RT::Action::$action";
  my $action_obj = $action->new(
    TicketObj     => $ticket,
    Argument      => $argument,
    Scrip         => $void{'Scrip'},
    ScripAction   => $void{'ScripAction'},
    CurrentUser   => $CurrentUser,
  );
  if ( $action_obj->Prepare ) {
    warn "Action prepared: $action\n" if $DEBUG;
    return $action_obj;
  }
  else {
    return;
  }
}

1;