group editing seems to be working... everything except defaults... oh and
[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 #false laziness w/part_export.pm
82 sub insert {
83   my $self = shift;
84
85   local $SIG{HUP} = 'IGNORE';
86   local $SIG{INT} = 'IGNORE';
87   local $SIG{QUIT} = 'IGNORE';
88   local $SIG{TERM} = 'IGNORE';
89   local $SIG{TSTP} = 'IGNORE';
90   local $SIG{PIPE} = 'IGNORE';
91
92   my $oldAutoCommit = $FS::UID::AutoCommit;
93   local $FS::UID::AutoCommit = 0;
94   my $dbh = dbh;
95
96   my $error = $self->SUPER::insert;
97   if ( $error ) {
98     $dbh->rollback if $oldAutoCommit;
99     return $error;
100   }
101
102   foreach my $arg ( @_ ) {
103     my $queue_arg = new FS::queue_arg ( {
104       'jobnum' => $self->jobnum,
105       'arg'    => $arg,
106     } );
107     $error = $queue_arg->insert;
108     if ( $error ) {
109       $dbh->rollback if $oldAutoCommit;
110       return $error;
111     }
112   }
113
114   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
115
116   '';
117
118 }
119
120 =item delete
121
122 Delete this record from the database.  Any corresponding queue_arg records are
123 deleted as well
124
125 =cut
126
127 sub delete {
128   my $self = shift;
129
130   local $SIG{HUP} = 'IGNORE';
131   local $SIG{INT} = 'IGNORE';
132   local $SIG{QUIT} = 'IGNORE';
133   local $SIG{TERM} = 'IGNORE';
134   local $SIG{TSTP} = 'IGNORE';
135   local $SIG{PIPE} = 'IGNORE';
136
137   my $oldAutoCommit = $FS::UID::AutoCommit;
138   local $FS::UID::AutoCommit = 0;
139   my $dbh = dbh;
140
141   my @args = qsearch( 'queue_arg', { 'jobnum' => $self->jobnum } );
142
143   my $error = $self->SUPER::delete;
144   if ( $error ) {
145     $dbh->rollback if $oldAutoCommit;
146     return $error;
147   }
148
149   foreach my $arg ( @args ) {
150     $error = $arg->delete;
151     if ( $error ) {
152       $dbh->rollback if $oldAutoCommit;
153       return $error;
154     }
155   }
156
157   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
158
159   '';
160
161 }
162
163 =item replace OLD_RECORD
164
165 Replaces the OLD_RECORD with this one in the database.  If there is an error,
166 returns the error, otherwise returns false.
167
168 =cut
169
170 # the replace method can be inherited from FS::Record
171
172 =item check
173
174 Checks all fields to make sure this is a valid job.  If there is
175 an error, returns the error, otherwise returns false.  Called by the insert
176 and replace methods.
177
178 =cut
179
180 sub check {
181   my $self = shift;
182   my $error =
183     $self->ut_numbern('jobnum')
184     || $self->ut_anything('job')
185     || $self->ut_numbern('_date')
186     || $self->ut_enum('status',['', qw( new locked failed )])
187     || $self->ut_textn('statustext')
188     || $self->ut_numbern('svcnum')
189   ;
190   return $error if $error;
191
192   $error = $self->ut_foreign_keyn('svcnum', 'cust_svc', 'svcnum');
193   $self->svcnum('') if $error;
194
195   $self->status('new') unless $self->status;
196   $self->_date(time) unless $self->_date;
197
198   ''; #no error
199 }
200
201 =item args
202
203 =cut
204
205 sub args {
206   my $self = shift;
207   map $_->arg, qsearch( 'queue_arg',
208                         { 'jobnum' => $self->jobnum },
209                         '',
210                         'ORDER BY argnum'
211                       );
212 }
213
214 =item cust_svc
215
216 Returns the FS::cust_svc object associated with this job, if any.
217
218 =cut
219
220 sub cust_svc {
221   my $self = shift;
222   qsearchs('cust_svc', { 'svcnum' => $self->svcnum } );
223 }
224
225 =item joblisting HASHREF NOACTIONS
226
227 =cut
228
229 sub joblisting {
230   my($hashref, $noactions) = @_;
231
232   use Date::Format;
233   use FS::CGI;
234
235   my @queue = qsearch( 'queue', $hashref );
236   return '' unless scalar(@queue);
237
238   my $html = FS::CGI::table(). <<END;
239       <TR>
240         <TH COLSPAN=2>Job</TH>
241         <TH>Args</TH>
242         <TH>Date</TH>
243         <TH>Status</TH>
244 END
245   $html .= '<TH>Account</TH>' unless $hashref->{svcnum};
246   $html .= '</TR>';
247
248   my $p = FS::CGI::popurl(2);
249   foreach my $queue ( sort { 
250     $a->getfield('jobnum') <=> $b->getfield('jobnum')
251   } @queue ) {
252     my $queue_hashref = $queue->hashref;
253     my $jobnum = $queue->jobnum;
254     my $args = join(' ', $queue->args);
255     my $date = time2str( "%a %b %e %T %Y", $queue->_date );
256     my $status = $queue->status;
257     $status .= ': '. $queue->statustext if $queue->statustext;
258     if ( ! $noactions && $status =~ /^failed/ || $status =~ /^locked/ ) {
259       $status .=
260         qq! (&nbsp;<A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=new">retry</A>&nbsp;|!.
261         qq!&nbsp;<A HREF="$p/misc/queue.cgi?jobnum=$jobnum&action=del">remove</A>&nbsp;)!;
262     }
263     my $cust_svc = $queue->cust_svc;
264
265     $html .= <<END;
266       <TR>
267         <TD>$jobnum</TD>
268         <TD>$queue_hashref->{job}</TD>
269         <TD>$args</TD>
270         <TD>$date</TD>
271         <TD>$status</TD>
272 END
273
274     unless ( $hashref->{svcnum} ) {
275       my $account;
276       if ( $cust_svc ) {
277         my $table = $cust_svc->part_svc->svcdb;
278         my $label = ( $cust_svc->label )[1];
279         $account = qq!<A HREF="../view/$table.cgi?!. $queue->svcnum.
280                    qq!">$label</A>!;
281       } else {
282         $account = '';
283       }
284       $html .= "<TD>$account</TD>";
285     }
286
287     $html .= '</TR>';
288
289 }
290
291   $html .= '</TABLE>';
292
293   $html;
294
295 }
296
297 =back
298
299 =head1 VERSION
300
301 $Id: queue.pm,v 1.8 2002-03-23 16:16:00 ivan Exp $
302
303 =head1 BUGS
304
305 =head1 SEE ALSO
306
307 L<FS::Record>, schema.html from the base documentation.
308
309 =cut
310
311 1;
312