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