X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fsvc_Common.pm;h=2fed5dd8a57408b68de6a064db33ac89eabfdbb8;hp=5bea5b0ce479436a1b95f2de9e5081129510a12e;hb=9ae101389f2fe652575c6ab314a5e95c2283b72e;hpb=6cd87c0d3b5280446301c647fa5f1ec5a593fa3f diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index 5bea5b0ce..2fed5dd8a 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -1,10 +1,11 @@ package FS::svc_Common; use strict; -use vars qw( @ISA ); -use FS::Record qw( qsearchs fields ); +use vars qw( @ISA $noexport_hack ); +use FS::Record qw( qsearch qsearchs fields dbh ); use FS::cust_svc; use FS::part_svc; +use FS::queue; @ISA = qw( FS::Record ); @@ -27,7 +28,59 @@ inherit from, i.e. FS::svc_acct. FS::svc_Common inherits from FS::Record. =over 4 -=item insert +=cut + +sub virtual_fields { + + # This restricts the fields based on part_svc_column and the svcpart of + # the service. There are four possible cases: + # 1. svcpart passed as part of the svc_x hash. + # 2. svcpart fetched via cust_svc based on svcnum. + # 3. No svcnum or svcpart. In this case, return ALL the fields with + # dbtable eq $self->table. + # 4. Called via "fields('svc_acct')" or something similar. In this case + # there is no $self object. + + my $self = shift; + my $svcpart; + my @vfields = $self->SUPER::virtual_fields; + + return @vfields unless (ref $self); # Case 4 + + if ($self->svcpart) { # Case 1 + $svcpart = $self->svcpart; + } elsif (my $cust_svc = $self->cust_svc) { # Case 2 + $svcpart = $cust_svc->svcpart; + } else { # Case 3 + $svcpart = ''; + } + + if ($svcpart) { #Cases 1 and 2 + my %flags = map { $_->columnname, $_->columnflag } ( + qsearch ('part_svc_column', { svcpart => $svcpart } ) + ); + return grep { not ($flags{$_} eq 'X') } @vfields; + } else { # Case 3 + return @vfields; + } + return (); +} + +=item check + +Checks the validity of fields in this record. + +At present, this does nothing but call FS::Record::check (which, in turn, +does nothing but run virtual field checks). + +=cut + +sub check { + my $self = shift; + $self->SUPER::check; +} + +=item insert [ JOBNUM_ARRAYREF [ OBJECTS_ARRAYREF ] ] Adds this record to the database. If there is an error, returns the error, otherwise returns false. @@ -35,10 +88,19 @@ otherwise returns false. The additional fields pkgnum and svcpart (see L) should be defined. An FS::cust_svc record will be created and inserted. +If an arrayref is passed as parameter, the Bs of any export jobs will +be added to the array. + +If an arrayref of FS::tablename objects (for example, FS::acct_snarf objects) +is passed as the optional second parameter, they will have their svcnum fields +set and will be inserted after this record, but before any exports are run. + =cut sub insert { my $self = shift; + local $FS::queue::jobnums = shift if @_; + my $objects = scalar(@_) ? shift : []; my $error; local $SIG{HUP} = 'IGNORE'; @@ -48,6 +110,10 @@ sub insert { local $SIG{TSTP} = 'IGNORE'; local $SIG{PIPE} = 'IGNORE'; + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + $error = $self->check; return $error if $error; @@ -55,21 +121,55 @@ sub insert { my $cust_svc; unless ( $svcnum ) { $cust_svc = new FS::cust_svc ( { - 'svcnum' => $svcnum, + #hua?# 'svcnum' => $svcnum, 'pkgnum' => $self->pkgnum, 'svcpart' => $self->svcpart, } ); $error = $cust_svc->insert; - return $error if $error; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } $svcnum = $self->svcnum($cust_svc->svcnum); + } else { + $cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum}); + unless ( $cust_svc ) { + $dbh->rollback if $oldAutoCommit; + return "no cust_svc record found for svcnum ". $self->svcnum; + } + $self->pkgnum($cust_svc->pkgnum); + $self->svcpart($cust_svc->svcpart); } $error = $self->SUPER::insert; if ( $error ) { - $cust_svc->delete if $cust_svc; + $dbh->rollback if $oldAutoCommit; return $error; } + foreach my $object ( @$objects ) { + $object->svcnum($self->svcnum); + $error = $object->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + + #new-style exports! + unless ( $noexport_hack ) { + foreach my $part_export ( $self->cust_svc->part_svc->part_export ) { + my $error = $part_export->export_insert($self); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; } @@ -95,16 +195,80 @@ sub delete { my $svcnum = $self->svcnum; + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + $error = $self->SUPER::delete; return $error if $error; - my $cust_svc = qsearchs( 'cust_svc' , { 'svcnum' => $svcnum } ); + #new-style exports! + unless ( $noexport_hack ) { + foreach my $part_export ( $self->cust_svc->part_svc->part_export ) { + my $error = $part_export->export_delete($self); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + + return $error if $error; + + my $cust_svc = $self->cust_svc; $error = $cust_svc->delete; return $error if $error; + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; } +=item replace OLD_RECORD + +Replaces OLD_RECORD with this one. If there is an error, returns the error, +otherwise returns false. + +=cut + +sub replace { + my ($new, $old) = (shift, shift); + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + my $error = $new->SUPER::replace($old); + if ($error) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + #new-style exports! + unless ( $noexport_hack ) { + foreach my $part_export ( $new->cust_svc->part_svc->part_export ) { + my $error = $part_export->export_replace($new,$old); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; +} + + =item setfixed Sets any fixed fields for this service (see L). If there is an @@ -145,7 +309,7 @@ sub setx { #get part_svc my $svcpart; if ( $self->svcnum ) { - my $cust_svc = qsearchs( 'cust_svc', { 'svcnum' => $self->svcnum } ); + my $cust_svc = $self->cust_svc; return "Unknown svcnum" unless $cust_svc; $svcpart = $cust_svc->svcpart; } else { @@ -155,9 +319,11 @@ sub setx { return "Unkonwn svcpart" unless $part_svc; #set default/fixed/whatever fields from part_svc - foreach my $field ( fields('svc_acct') ) { - if ( $part_svc->getfield('svc_acct__'. $field. '_flag') eq $x ) { - $self->setfield( $field, $part_svc->getfield('svc_acct__'. $field) ); + my $table = $self->table; + foreach my $field ( grep { $_ ne 'svcnum' } $self->fields ) { + my $part_svc_column = $part_svc->part_svc_column($field); + if ( $part_svc_column->columnflag eq $x ) { + $self->setfield( $field, $part_svc_column->columnvalue ); } } @@ -165,34 +331,111 @@ sub setx { } +=item cust_svc + +Returns the cust_svc record associated with this svc_ record, as a FS::cust_svc +object (see L). + +=cut + +sub cust_svc { + my $self = shift; + qsearchs('cust_svc', { 'svcnum' => $self->svcnum } ); +} + =item suspend +Runs export_suspend callbacks. + +=cut + +sub suspend { + my $self = shift; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + #new-style exports! + unless ( $noexport_hack ) { + foreach my $part_export ( $self->cust_svc->part_svc->part_export ) { + my $error = $part_export->export_suspend($self); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + =item unsuspend +Runs export_unsuspend callbacks. + +=cut + +sub unsuspend { + my $self = shift; + + local $SIG{HUP} = 'IGNORE'; + local $SIG{INT} = 'IGNORE'; + local $SIG{QUIT} = 'IGNORE'; + local $SIG{TERM} = 'IGNORE'; + local $SIG{TSTP} = 'IGNORE'; + local $SIG{PIPE} = 'IGNORE'; + + my $oldAutoCommit = $FS::UID::AutoCommit; + local $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + #new-style exports! + unless ( $noexport_hack ) { + foreach my $part_export ( $self->cust_svc->part_svc->part_export ) { + my $error = $part_export->export_unsuspend($self); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + ''; + +} + =item cancel -Stubs - return false (no error) so derived classes don't need to define these +Stub - returns false (no error) so derived classes don't need to define these methods. Called by the cancel method of FS::cust_pkg (see L). =cut -sub suspend { ''; } -sub unsuspend { ''; } sub cancel { ''; } =back =head1 VERSION -$Id: svc_Common.pm,v 1.1 1999-08-04 09:03:53 ivan Exp $ +$Id: svc_Common.pm,v 1.14 2003-10-25 02:05:44 ivan Exp $ =head1 BUGS The setfixed method return value. -The new method should set defaults from part_svc (like the check method -sets fixed values)? - =head1 SEE ALSO L, L, L, L, schema.html