1 package FS::svc_Common;
4 use vars qw( @ISA $noexport_hack );
5 use FS::Record qw( qsearch qsearchs fields dbh );
10 @ISA = qw( FS::Record );
14 FS::svc_Common - Object method for all svc_ records
20 @ISA = qw( FS::svc_Common );
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.
35 # This restricts the fields based on part_svc_column and the svcpart of
36 # the service. There are four possible cases:
37 # 1. svcpart passed as part of the svc_x hash.
38 # 2. svcpart fetched via cust_svc based on svcnum.
39 # 3. No svcnum or svcpart. In this case, return ALL the fields with
40 # dbtable eq $self->table.
41 # 4. Called via "fields('svc_acct')" or something similar. In this case
42 # there is no $self object.
46 my @vfields = $self->SUPER::virtual_fields;
48 return @vfields unless (ref $self); # Case 4
50 if ($self->svcpart) { # Case 1
51 $svcpart = $self->svcpart;
52 } elsif ( $self->svcnum
53 && qsearchs('cust_svc',{'svcnum'=>$self->svcnum} )
55 $svcpart = $self->cust_svc->svcpart;
60 if ($svcpart) { #Cases 1 and 2
61 my %flags = map { $_->columnname, $_->columnflag } (
62 qsearch ('part_svc_column', { svcpart => $svcpart } )
64 return grep { not ($flags{$_} eq 'X') } @vfields;
73 Checks the validity of fields in this record.
75 At present, this does nothing but call FS::Record::check (which, in turn,
76 does nothing but run virtual field checks).
85 =item insert [ JOBNUM_ARRAYREF [ OBJECTS_ARRAYREF ] ]
87 Adds this record to the database. If there is an error, returns the error,
88 otherwise returns false.
90 The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
91 defined. An FS::cust_svc record will be created and inserted.
93 If an arrayref is passed as parameter, the B<jobnum>s of any export jobs will
94 be added to the array.
96 If an arrayref of FS::tablename objects (for example, FS::acct_snarf objects)
97 is passed as the optional second parameter, they will have their svcnum fields
98 set and will be inserted after this record, but before any exports are run.
104 local $FS::queue::jobnums = shift if @_;
105 my $objects = scalar(@_) ? shift : [];
108 local $SIG{HUP} = 'IGNORE';
109 local $SIG{INT} = 'IGNORE';
110 local $SIG{QUIT} = 'IGNORE';
111 local $SIG{TERM} = 'IGNORE';
112 local $SIG{TSTP} = 'IGNORE';
113 local $SIG{PIPE} = 'IGNORE';
115 my $oldAutoCommit = $FS::UID::AutoCommit;
116 local $FS::UID::AutoCommit = 0;
119 $error = $self->check;
120 return $error if $error;
122 my $svcnum = $self->svcnum;
123 my $cust_svc = $svcnum ? qsearchs('cust_svc',{'svcnum'=>$self->svcnum}) : '';
124 #unless ( $svcnum ) {
125 if ( !$svcnum or !$cust_svc ) {
126 $cust_svc = new FS::cust_svc ( {
127 #hua?# 'svcnum' => $svcnum,
128 'svcnum' => $self->svcnum,
129 'pkgnum' => $self->pkgnum,
130 'svcpart' => $self->svcpart,
132 $error = $cust_svc->insert;
134 $dbh->rollback if $oldAutoCommit;
137 $svcnum = $self->svcnum($cust_svc->svcnum);
139 #$cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
140 unless ( $cust_svc ) {
141 $dbh->rollback if $oldAutoCommit;
142 return "no cust_svc record found for svcnum ". $self->svcnum;
144 $self->pkgnum($cust_svc->pkgnum);
145 $self->svcpart($cust_svc->svcpart);
148 $error = $self->SUPER::insert;
150 $dbh->rollback if $oldAutoCommit;
154 foreach my $object ( @$objects ) {
155 $object->svcnum($self->svcnum);
156 $error = $object->insert;
158 $dbh->rollback if $oldAutoCommit;
164 unless ( $noexport_hack ) {
165 foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
166 my $error = $part_export->export_insert($self);
168 $dbh->rollback if $oldAutoCommit;
169 return "exporting to ". $part_export->exporttype.
170 " (transaction rolled back): $error";
175 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
182 Deletes this account from the database. If there is an error, returns the
183 error, otherwise returns false.
185 The corresponding FS::cust_svc record will be deleted as well.
193 local $SIG{HUP} = 'IGNORE';
194 local $SIG{INT} = 'IGNORE';
195 local $SIG{QUIT} = 'IGNORE';
196 local $SIG{TERM} = 'IGNORE';
197 local $SIG{TSTP} = 'IGNORE';
198 local $SIG{PIPE} = 'IGNORE';
200 my $svcnum = $self->svcnum;
202 my $oldAutoCommit = $FS::UID::AutoCommit;
203 local $FS::UID::AutoCommit = 0;
206 $error = $self->SUPER::delete;
207 return $error if $error;
210 unless ( $noexport_hack ) {
211 foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
212 my $error = $part_export->export_delete($self);
214 $dbh->rollback if $oldAutoCommit;
215 return "exporting to ". $part_export->exporttype.
216 " (transaction rolled back): $error";
221 return $error if $error;
223 my $cust_svc = $self->cust_svc;
224 $error = $cust_svc->delete;
225 return $error if $error;
227 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
232 =item replace OLD_RECORD
234 Replaces OLD_RECORD with this one. If there is an error, returns the error,
235 otherwise returns false.
240 my ($new, $old) = (shift, shift);
242 local $SIG{HUP} = 'IGNORE';
243 local $SIG{INT} = 'IGNORE';
244 local $SIG{QUIT} = 'IGNORE';
245 local $SIG{TERM} = 'IGNORE';
246 local $SIG{TSTP} = 'IGNORE';
247 local $SIG{PIPE} = 'IGNORE';
249 my $oldAutoCommit = $FS::UID::AutoCommit;
250 local $FS::UID::AutoCommit = 0;
253 my $error = $new->SUPER::replace($old);
255 $dbh->rollback if $oldAutoCommit;
260 unless ( $noexport_hack ) {
261 foreach my $part_export ( $new->cust_svc->part_svc->part_export ) {
262 my $error = $part_export->export_replace($new,$old);
264 $dbh->rollback if $oldAutoCommit;
265 return "error exporting to ". $part_export->exporttype.
266 " (transaction rolled back): $error";
271 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
278 Sets any fixed fields for this service (see L<FS::part_svc>). If there is an
279 error, returns the error, otherwise returns the FS::part_svc object (use ref()
280 to test the return). Usually called by the check method.
291 Sets all fields to their defaults (see L<FS::part_svc>), overriding their
292 current values. If there is an error, returns the error, otherwise returns
293 the FS::part_svc object (use ref() to test the return).
309 $self->ut_numbern('svcnum')
311 return $error if $error;
315 if ( $self->svcnum && qsearchs('cust_svc', {'svcnum'=>$self->svcnum}) ) {
316 my $cust_svc = $self->cust_svc;
317 return "Unknown svcnum" unless $cust_svc;
318 $svcpart = $cust_svc->svcpart;
320 $svcpart = $self->getfield('svcpart');
322 my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
323 return "Unkonwn svcpart" unless $part_svc;
325 #set default/fixed/whatever fields from part_svc
326 my $table = $self->table;
327 foreach my $field ( grep { $_ ne 'svcnum' } $self->fields ) {
328 my $part_svc_column = $part_svc->part_svc_column($field);
329 if ( $part_svc_column->columnflag eq $x ) {
330 $self->setfield( $field, $part_svc_column->columnvalue );
340 Returns the cust_svc record associated with this svc_ record, as a FS::cust_svc
341 object (see L<FS::cust_svc>).
347 qsearchs('cust_svc', { 'svcnum' => $self->svcnum } );
352 Runs export_suspend callbacks.
359 local $SIG{HUP} = 'IGNORE';
360 local $SIG{INT} = 'IGNORE';
361 local $SIG{QUIT} = 'IGNORE';
362 local $SIG{TERM} = 'IGNORE';
363 local $SIG{TSTP} = 'IGNORE';
364 local $SIG{PIPE} = 'IGNORE';
366 my $oldAutoCommit = $FS::UID::AutoCommit;
367 local $FS::UID::AutoCommit = 0;
371 unless ( $noexport_hack ) {
372 foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
373 my $error = $part_export->export_suspend($self);
375 $dbh->rollback if $oldAutoCommit;
376 return "error exporting to ". $part_export->exporttype.
377 " (transaction rolled back): $error";
382 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
389 Runs export_unsuspend callbacks.
396 local $SIG{HUP} = 'IGNORE';
397 local $SIG{INT} = 'IGNORE';
398 local $SIG{QUIT} = 'IGNORE';
399 local $SIG{TERM} = 'IGNORE';
400 local $SIG{TSTP} = 'IGNORE';
401 local $SIG{PIPE} = 'IGNORE';
403 my $oldAutoCommit = $FS::UID::AutoCommit;
404 local $FS::UID::AutoCommit = 0;
408 unless ( $noexport_hack ) {
409 foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
410 my $error = $part_export->export_unsuspend($self);
412 $dbh->rollback if $oldAutoCommit;
413 return "error exporting to ". $part_export->exporttype.
414 " (transaction rolled back): $error";
419 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
426 Stub - returns false (no error) so derived classes don't need to define these
427 methods. Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
433 =item clone_suspended
435 Constructor used by FS::part_export::_export_suspend fallback. Stub returning
436 same object for svc_ classes which don't implement a suspension fallback
437 (everything except svc_acct at the moment). Document better.
441 sub clone_suspended {
445 =item clone_kludge_unsuspend
447 Constructor used by FS::part_export::_export_unsuspend fallback. Stub returning
448 same object for svc_ classes which don't implement a suspension fallback
449 (everything except svc_acct at the moment). Document better.
453 sub clone_kludge_unsuspend {
461 The setfixed method return value.
465 L<FS::Record>, L<FS::cust_svc>, L<FS::part_svc>, L<FS::cust_pkg>, schema.html
466 from the base documentation.