working job dependancies
[freeside.git] / FS / FS / svc_Common.pm
1 package FS::svc_Common;
2
3 use strict;
4 use vars qw( @ISA $noexport_hack );
5 use FS::Record qw( qsearchs fields dbh );
6 use FS::cust_svc;
7 use FS::part_svc;
8 use FS::queue;
9
10 @ISA = qw( FS::Record );
11
12 =head1 NAME
13
14 FS::svc_Common - Object method for all svc_ records
15
16 =head1 SYNOPSIS
17
18 use FS::svc_Common;
19
20 @ISA = qw( FS::svc_Common );
21
22 =head1 DESCRIPTION
23
24 FS::svc_Common is intended as a base class for table-specific classes to
25 inherit from, i.e. FS::svc_acct.  FS::svc_Common inherits from FS::Record.
26
27 =head1 METHODS
28
29 =over 4
30
31 =item insert [ JOBNUM_ARRAYREF ]
32
33 Adds this record to the database.  If there is an error, returns the error,
34 otherwise returns false.
35
36 The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be 
37 defined.  An FS::cust_svc record will be created and inserted.
38
39 If an arrayref is passed as parameter, the B<jobnum>s of any export jobs will
40 be added to the array.
41
42 =cut
43
44 sub insert {
45   my $self = shift;
46   local $FS::queue::jobnums = shift if @_;
47   my $error;
48
49   local $SIG{HUP} = 'IGNORE';
50   local $SIG{INT} = 'IGNORE';
51   local $SIG{QUIT} = 'IGNORE';
52   local $SIG{TERM} = 'IGNORE';
53   local $SIG{TSTP} = 'IGNORE';
54   local $SIG{PIPE} = 'IGNORE';
55
56   my $oldAutoCommit = $FS::UID::AutoCommit;
57   local $FS::UID::AutoCommit = 0;
58   my $dbh = dbh;
59
60   $error = $self->check;
61   return $error if $error;
62
63   my $svcnum = $self->svcnum;
64   my $cust_svc;
65   unless ( $svcnum ) {
66     $cust_svc = new FS::cust_svc ( {
67       #hua?# 'svcnum'  => $svcnum,
68       'pkgnum'  => $self->pkgnum,
69       'svcpart' => $self->svcpart,
70     } );
71     $error = $cust_svc->insert;
72     if ( $error ) {
73       $dbh->rollback if $oldAutoCommit;
74       return $error;
75     }
76     $svcnum = $self->svcnum($cust_svc->svcnum);
77   } else {
78     $cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
79     unless ( $cust_svc ) {
80       $dbh->rollback if $oldAutoCommit;
81       return "no cust_svc record found for svcnum ". $self->svcnum;
82     }
83     $self->pkgnum($cust_svc->pkgnum);
84     $self->svcpart($cust_svc->svcpart);
85   }
86
87   $error = $self->SUPER::insert;
88   if ( $error ) {
89     $dbh->rollback if $oldAutoCommit;
90     return $error;
91   }
92
93   #new-style exports!
94   unless ( $noexport_hack ) {
95     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
96       my $error = $part_export->export_insert($self);
97       if ( $error ) {
98         $dbh->rollback if $oldAutoCommit;
99         return "exporting to ". $part_export->exporttype.
100                " (transaction rolled back): $error";
101       }
102     }
103   }
104
105   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
106
107   '';
108 }
109
110 =item delete
111
112 Deletes this account from the database.  If there is an error, returns the
113 error, otherwise returns false.
114
115 The corresponding FS::cust_svc record will be deleted as well.
116
117 =cut
118
119 sub delete {
120   my $self = shift;
121   my $error;
122
123   local $SIG{HUP} = 'IGNORE';
124   local $SIG{INT} = 'IGNORE';
125   local $SIG{QUIT} = 'IGNORE';
126   local $SIG{TERM} = 'IGNORE';
127   local $SIG{TSTP} = 'IGNORE';
128   local $SIG{PIPE} = 'IGNORE';
129
130   my $svcnum = $self->svcnum;
131
132   my $oldAutoCommit = $FS::UID::AutoCommit;
133   local $FS::UID::AutoCommit = 0;
134   my $dbh = dbh;
135
136   $error = $self->SUPER::delete;
137   return $error if $error;
138
139   #new-style exports!
140   unless ( $noexport_hack ) {
141     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
142       my $error = $part_export->export_delete($self);
143       if ( $error ) {
144         $dbh->rollback if $oldAutoCommit;
145         return "exporting to ". $part_export->exporttype.
146                " (transaction rolled back): $error";
147       }
148     }
149   }
150
151   return $error if $error;
152
153   my $cust_svc = $self->cust_svc;
154   $error = $cust_svc->delete;
155   return $error if $error;
156
157   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
158
159   '';
160 }
161
162 =item replace OLD_RECORD
163
164 Replaces OLD_RECORD with this one.  If there is an error, returns the error,
165 otherwise returns false.
166
167 =cut
168
169 sub replace {
170   my ($new, $old) = (shift, shift);
171
172   local $SIG{HUP} = 'IGNORE';
173   local $SIG{INT} = 'IGNORE';
174   local $SIG{QUIT} = 'IGNORE';
175   local $SIG{TERM} = 'IGNORE';
176   local $SIG{TSTP} = 'IGNORE';
177   local $SIG{PIPE} = 'IGNORE';
178
179   my $oldAutoCommit = $FS::UID::AutoCommit;
180   local $FS::UID::AutoCommit = 0;
181   my $dbh = dbh;
182
183   my $error = $new->SUPER::replace($old);
184   if ($error) {
185     $dbh->rollback if $oldAutoCommit;
186     return $error;
187   }
188
189   #new-style exports!
190   unless ( $noexport_hack ) {
191     foreach my $part_export ( $new->cust_svc->part_svc->part_export ) {
192       my $error = $part_export->export_replace($new,$old);
193       if ( $error ) {
194         $dbh->rollback if $oldAutoCommit;
195         return "error exporting to ". $part_export->exporttype.
196                " (transaction rolled back): $error";
197       }
198     }
199   }
200
201   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
202   '';
203 }
204
205
206 =item setfixed
207
208 Sets any fixed fields for this service (see L<FS::part_svc>).  If there is an
209 error, returns the error, otherwise returns the FS::part_svc object (use ref()
210 to test the return).  Usually called by the check method.
211
212 =cut
213
214 sub setfixed {
215   my $self = shift;
216   $self->setx('F');
217 }
218
219 =item setdefault
220
221 Sets all fields to their defaults (see L<FS::part_svc>), overriding their
222 current values.  If there is an error, returns the error, otherwise returns
223 the FS::part_svc object (use ref() to test the return).
224
225 =cut
226
227 sub setdefault {
228   my $self = shift;
229   $self->setx('D');
230 }
231
232 sub setx {
233   my $self = shift;
234   my $x = shift;
235
236   my $error;
237
238   $error =
239     $self->ut_numbern('svcnum')
240   ;
241   return $error if $error;
242
243   #get part_svc
244   my $svcpart;
245   if ( $self->svcnum ) {
246     my $cust_svc = $self->cust_svc;
247     return "Unknown svcnum" unless $cust_svc; 
248     $svcpart = $cust_svc->svcpart;
249   } else {
250     $svcpart = $self->getfield('svcpart');
251   }
252   my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
253   return "Unkonwn svcpart" unless $part_svc;
254
255   #set default/fixed/whatever fields from part_svc
256   my $table = $self->table;
257   foreach my $field ( grep { $_ ne 'svcnum' } fields($table) ) {
258     my $part_svc_column = $part_svc->part_svc_column($field);
259     if ( $part_svc_column->columnflag eq $x ) {
260       $self->setfield( $field, $part_svc_column->columnvalue );
261     }
262   }
263
264  $part_svc;
265
266 }
267
268 =item cust_svc
269
270 Returns the cust_svc record associated with this svc_ record, as a FS::cust_svc
271 object (see L<FS::cust_svc>).
272
273 =cut
274
275 sub cust_svc {
276   my $self = shift;
277   qsearchs('cust_svc', { 'svcnum' => $self->svcnum } );
278 }
279
280 =item suspend
281
282 Runs export_suspend callbacks.
283
284 =cut
285
286 sub suspend {
287   my $self = shift;
288
289   local $SIG{HUP} = 'IGNORE';
290   local $SIG{INT} = 'IGNORE';
291   local $SIG{QUIT} = 'IGNORE';
292   local $SIG{TERM} = 'IGNORE';
293   local $SIG{TSTP} = 'IGNORE';
294   local $SIG{PIPE} = 'IGNORE';
295
296   my $oldAutoCommit = $FS::UID::AutoCommit;
297   local $FS::UID::AutoCommit = 0;
298   my $dbh = dbh;
299
300   #new-style exports!
301   unless ( $noexport_hack ) {
302     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
303       my $error = $part_export->export_suspend($self);
304       if ( $error ) {
305         $dbh->rollback if $oldAutoCommit;
306         return "error exporting to ". $part_export->exporttype.
307                " (transaction rolled back): $error";
308       }
309     }
310   }
311
312   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
313   '';
314
315 }
316
317 =item unsuspend
318
319 Runs export_unsuspend callbacks.
320
321 =cut
322
323 sub unsuspend {
324   my $self = shift;
325
326   local $SIG{HUP} = 'IGNORE';
327   local $SIG{INT} = 'IGNORE';
328   local $SIG{QUIT} = 'IGNORE';
329   local $SIG{TERM} = 'IGNORE';
330   local $SIG{TSTP} = 'IGNORE';
331   local $SIG{PIPE} = 'IGNORE';
332
333   my $oldAutoCommit = $FS::UID::AutoCommit;
334   local $FS::UID::AutoCommit = 0;
335   my $dbh = dbh;
336
337   #new-style exports!
338   unless ( $noexport_hack ) {
339     foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
340       my $error = $part_export->export_unsuspend($self);
341       if ( $error ) {
342         $dbh->rollback if $oldAutoCommit;
343         return "error exporting to ". $part_export->exporttype.
344                " (transaction rolled back): $error";
345       }
346     }
347   }
348
349   $dbh->commit or die $dbh->errstr if $oldAutoCommit;
350   '';
351
352 }
353
354 =item cancel
355
356 Stub - returns false (no error) so derived classes don't need to define these
357 methods.  Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
358
359 =cut
360
361 sub cancel { ''; }
362
363 =back
364
365 =head1 VERSION
366
367 $Id: svc_Common.pm,v 1.12 2002-06-14 11:22:53 ivan Exp $
368
369 =head1 BUGS
370
371 The setfixed method return value.
372
373 =head1 SEE ALSO
374
375 L<FS::Record>, L<FS::cust_svc>, L<FS::part_svc>, L<FS::cust_pkg>, schema.html
376 from the base documentation.
377
378 =cut
379
380 1;
381