don't error out on bad svcnum's, just silently remove them
[freeside.git] / FS / FS / queue.pm
1 package FS::queue;
2
3 use strict;
4 use vars qw( @ISA @EXPORT_OK );
5 use Exporter;
6 use FS::Record qw( qsearch qsearchs dbh );
7 #use FS::queue;
8 use FS::queue_arg;
9 use FS::cust_svc;
10
11 @ISA = qw(FS::Record);
12 @EXPORT_OK = qw( joblisting );
13
14 =head1 NAME
15
16 FS::queue - Object methods for queue records
17
18 =head1 SYNOPSIS
19
20   use FS::queue;
21
22   $record = new FS::queue \%hash;
23   $record = new FS::queue { 'column' => 'value' };
24
25   $error = $record->insert;
26
27   $error = $new_record->replace($old_record);
28
29   $error = $record->delete;
30
31   $error = $record->check;
32
33 =head1 DESCRIPTION
34
35 An FS::queue object represents an queued job.  FS::queue inherits from
36 FS::Record.  The following fields are currently supported:
37
38 =over 4
39
40 =item jobnum - primary key
41
42 =item job - fully-qualified subroutine name
43
44 =item status - job status
45
46 =item statustext - freeform text status message
47
48 =item _date - UNIX timestamp
49
50 =item svcnum - optional link to service (see L<FS::cust_svc>)
51
52 =back
53
54 =head1 METHODS
55
56 =over 4
57
58 =item new HASHREF
59
60 Creates a new job.  To add the example to the database, see L<"insert">.
61
62 Note that this stores the hash reference, not a distinct copy of the hash it
63 points to.  You can ask the object for a copy with the I<hash> method.
64
65 =cut
66
67 # the new method can be inherited from FS::Record, if a table method is defined
68
69 sub table { 'queue'; }
70
71 =item insert [ ARGUMENT, ARGUMENT... ]
72
73 Adds this record to the database.  If there is an error, returns the error,
74 otherwise returns false.
75
76 If any arguments are supplied, a queue_arg record for each argument is also
77 created (see L<FS::queue_arg>).
78
79 =cut
80
81 sub insert {
82   my $self = shift;
83
84   local $SIG{HUP} = 'IGNORE';
85   local $SIG{INT} = 'IGNORE';
86   local $SIG{QUIT} = 'IGNORE';
87   local $SIG{TERM} = 'IGNORE';
88   local $SIG{TSTP} = 'IGNORE';
89   local $SIG{PIPE} = 'IGNORE';
90
91   my $oldAutoCommit = $FS::UID::AutoCommit;
92   local $FS::UID::AutoCommit = 0;
93   my $dbh = dbh;
94
95   my $error = $self->SUPER::insert;
96   if ( $error ) {
97     $dbh->rollback if $oldAutoCommit;
98     return $error;
99   }
100
101   foreach my $arg ( @_ ) {
102     my $queue_arg = new FS::queue_arg ( {
103       'jobnum' => $self->jobnum,
104       'arg'    => $arg,
105     } );
106     $error = $queue_arg->insert;
107     if ( $error ) {
108       $dbh->rollback if $oldAutoCommit;
109       return $error;
110     }
111   }
112
113   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
114
115   '';
116
117 }
118
119 =item delete
120
121 Delete this record from the database.  Any corresponding queue_arg records are
122 deleted as well
123
124 =cut
125
126 sub delete {
127   my $self = shift;
128
129   local $SIG{HUP} = 'IGNORE';
130   local $SIG{INT} = 'IGNORE';
131   local $SIG{QUIT} = 'IGNORE';
132   local $SIG{TERM} = 'IGNORE';
133   local $SIG{TSTP} = 'IGNORE';
134   local $SIG{PIPE} = 'IGNORE';
135
136   my $oldAutoCommit = $FS::UID::AutoCommit;
137   local $FS::UID::AutoCommit = 0;
138   my $dbh = dbh;
139
140   my @args = qsearch( 'queue_arg', { 'jobnum' => $self->jobnum } );
141
142   my $error = $self->SUPER::delete;
143   if ( $error ) {
144     $dbh->rollback if $oldAutoCommit;
145     return $error;
146   }
147
148   foreach my $arg ( @args ) {
149     $error = $arg->delete;
150     if ( $error ) {
151       $dbh->rollback if $oldAutoCommit;
152       return $error;
153     }
154   }
155
156   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
157
158   '';
159
160 }
161
162 =item replace OLD_RECORD
163
164 Replaces the OLD_RECORD with this one in the database.  If there is an error,
165 returns the error, otherwise returns false.
166
167 =cut
168
169 # the replace method can be inherited from FS::Record
170
171 =item check
172
173 Checks all fields to make sure this is a valid job.  If there is
174 an error, returns the error, otherwise returns false.  Called by the insert
175 and replace methods.
176
177 =cut
178
179 sub check {
180   my $self = shift;
181   my $error =
182     $self->ut_numbern('jobnum')
183     || $self->ut_anything('job')
184     || $self->ut_numbern('_date')
185     || $self->ut_enum('status',['', qw( new locked failed )])
186     || $self->ut_textn('statustext')
187     || $self->ut_numbern('svcnum')
188   ;
189   return $error if $error;
190
191   $error = $self->ut_foreign_keyn('svcnum', 'cust_svc', 'svcnum');
192   $self->svcnum('') if $error;
193
194   $self->status('new') unless $self->status;
195   $self->_date(time) unless $self->_date;
196
197   ''; #no error
198 }
199
200 =item args
201
202 =cut
203
204 sub args {
205   my $self = shift;
206   map $_->arg, qsearch( 'queue_arg',
207                         { 'jobnum' => $self->jobnum },
208                         '',
209                         'ORDER BY argnum'
210                       );
211 }
212
213 =item cust_svc
214
215 Returns the FS::cust_svc object associated with this job, if any.
216
217 =cut
218
219 sub cust_svc {
220   my $self = shift;
221   qsearchs('cust_svc', { 'svcnum' => $self->svcnum } );
222 }
223
224 =item joblisting HASHREF
225
226 =cut
227
228 sub joblisting {
229   my($hashref, $noactions) = @_;
230
231   use Date::Format;
232   use FS::CGI;
233
234   my $html = FS::CGI::table(). <<END;
235       <TR>
236         <TH COLSPAN=2>Job</TH>
237         <TH>Args</TH>
238         <TH>Date</TH>
239         <TH>Status</TH>
240         <TH>Account</TH>
241       </TR>
242 END
243
244   my $p = FS::CGI::popurl(2);
245   foreach my $queue ( sort { 
246     $a->getfield('jobnum') <=> $b->getfield('jobnum')
247   } qsearch( 'queue', $hashref ) ) {
248     my $hashref = $queue->hashref;
249     my $jobnum = $queue->jobnum;
250     my $args = join(' ', $queue->args);
251     my $date = time2str( "%a %b %e %T %Y", $queue->_date );
252     my $status = $queue->status;
253     $status .= ': '. $queue->statustext if $queue->statustext;
254     if ( ! $noactions && $status =~ /^failed/ || $status =~ /^locked/ ) {
255       $status .=
256         qq! ( <A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=new">retry</A> |!.
257         qq! <A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=del">remove </A> )!;
258     }
259     my $cust_svc = $queue->cust_svc;
260     my $account;
261     if ( $cust_svc ) {
262       my $table = $cust_svc->part_svc->svcdb;
263       my $label = ( $cust_svc->label )[1];
264       $account = qq!<A HREF="../view/$table.cgi?!. $queue->svcnum.
265                  qq!">$label</A>!;
266     } else {
267       $account = '';
268     }
269     $html .= <<END;
270       <TR>
271         <TD>$jobnum</TD>
272         <TD>$hashref->{job}</TD>
273         <TD>$args</TD>
274         <TD>$date</TD>
275         <TD>$status</TD>
276         <TD>$account</TD>
277       </TR>
278 END
279
280 }
281
282   $html .= '</TABLE>';
283
284   $html;
285
286 }
287
288 =back
289
290 =head1 VERSION
291
292 $Id: queue.pm,v 1.5 2002-02-22 06:39:23 ivan Exp $
293
294 =head1 BUGS
295
296 =head1 SEE ALSO
297
298 L<FS::Record>, schema.html from the base documentation.
299
300 =cut
301
302 1;
303