X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fsvc_Common.pm;h=4efdc23adf3bff9644ca6798475a081529d34292;hb=dd825e780ad1e7d520f5c2d7f99c0f67fe892781;hp=9137c3f69a6fc79485efa4bcaacc75bfb7f4a32f;hpb=34d1b9d0053e3946a7a64a83966b8428da5a852c;p=freeside.git diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index 9137c3f69..4efdc23ad 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -5,6 +5,7 @@ use vars qw( @ISA $noexport_hack $DEBUG $me $overlimit_missing_cust_svc_nonfatal_kludge ); use Carp qw( cluck carp croak confess ); #specify cluck have to specify them all use Scalar::Util qw( blessed ); +use Lingua::EN::Inflect qw( PL_N ); use FS::Conf; use FS::Record qw( qsearch qsearchs fields dbh ); use FS::cust_main_Mixin; @@ -199,12 +200,13 @@ I. If I is set to an array reference, the jobnums of any export jobs will be added to the referenced array. -If I is set to an array reference of FS::tablename objects (for -example, FS::acct_snarf objects), they will have their svcnum field set and -will be inserted after this record, but before any exports are run. Each -element of the array can also optionally be a two-element array reference -containing the child object and the name of an alternate field to be filled in -with the newly-inserted svcnum, for example C<[ $svc_forward, 'srcsvc' ]> +If I is set to an array reference of FS::tablename objects +(for example, FS::svc_export_machine or FS::acct_snarf objects), they +will have their svcnum field set and will be inserted after this record, +but before any exports are run. Each element of the array can also +optionally be a two-element array reference containing the child object +and the name of an alternate field to be filled in with the newly-inserted +svcnum, for example C<[ $svc_forward, 'srcsvc' ]> If I is set (to a scalar jobnum or an array reference of jobnums), all provisioning jobs will have a dependancy on the supplied @@ -243,6 +245,7 @@ sub insert { my $svcnum = $self->svcnum; my $cust_svc = $svcnum ? qsearchs('cust_svc',{'svcnum'=>$self->svcnum}) : ''; + my $inserted_cust_svc = 0; #unless ( $svcnum ) { if ( !$svcnum or !$cust_svc ) { $cust_svc = new FS::cust_svc ( { @@ -256,6 +259,7 @@ sub insert { $dbh->rollback if $oldAutoCommit; return $error; } + $inserted_cust_svc = 1; $svcnum = $self->svcnum($cust_svc->svcnum); } else { #$cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum}); @@ -274,6 +278,10 @@ sub insert { || $self->preinsert_hook || $self->SUPER::insert; if ( $error ) { + if ( $inserted_cust_svc ) { + my $derror = $cust_svc->delete; + die $derror if $derror; + } $dbh->rollback if $oldAutoCommit; return $error; } @@ -432,7 +440,16 @@ sub expire { Replaces OLD_RECORD with this one. If there is an error, returns the error, otherwise returns false. -Currently available options are: I and I. +Currently available options are: I, I and +I. + +If I is set to an array reference of FS::tablename objects +(for example, FS::svc_export_machine or FS::acct_snarf objects), they +will have their svcnum field set and will be inserted or replaced after +this record, but before any exports are run. Each element of the array +can also optionally be a two-element array reference containing the +child object and the name of an alternate field to be filled in with +the newly-inserted svcnum, for example C<[ $svc_forward, 'srcsvc' ]> If I is set (to a scalar jobnum or an array reference of jobnums), all provisioning jobs will have a dependancy on the supplied @@ -455,6 +472,8 @@ sub replace { ? shift : { @_ }; + my $objects = $options->{'child_objects'} || []; + my @jobnums = (); local $FS::queue::jobnums = \@jobnums; warn "[$me] replace: set \$FS::queue::jobnums to $FS::queue::jobnums\n" @@ -504,6 +523,34 @@ sub replace { return $error; } + foreach my $object ( @$objects ) { + my($field, $obj); + if ( ref($object) eq 'ARRAY' ) { + ($obj, $field) = @$object; + } else { + $obj = $object; + $field = 'svcnum'; + } + $obj->$field($new->svcnum); + + my $oldobj = qsearchs( $obj->table, { + $field => $new->svcnum, + map { $_ => $obj->$_ } $obj->_svc_child_partfields, + }); + + if ( $oldobj ) { + my $pkey = $oldobj->primary_key; + $obj->$pkey($oldobj->$pkey); + $obj->replace($oldobj); + } else { + $error = $obj->insert; + } + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + } + #new-style exports! unless ( $noexport_hack ) { @@ -844,8 +891,7 @@ sub set_auto_inventory { qsearchs('inventory_class', { 'classnum' => $classnum } ); return "Can't find inventory_class.classnum $classnum" unless $inventory_class; - return "Out of ". $inventory_class->classname. "s\n"; #Lingua:: BS - #for pluralizing + return "Out of ". PL_N($inventory_class->classname); } next if $columnflag eq 'M' && $inventory_item->svcnum == $self->svcnum; @@ -853,31 +899,38 @@ sub set_auto_inventory { $self->setfield( $field, $inventory_item->item ); #if $columnflag eq 'A' && $self->$field() eq ''; - $inventory_item->svcnum( $self->svcnum ); - my $ierror = $inventory_item->replace(); - if ( $ierror ) { - $dbh->rollback if $oldAutoCommit; - return "Error provisioning inventory: $ierror"; - } - if ( $old && $old->$field() && $old->$field() ne $self->$field() ) { my $old_inv = qsearchs({ - 'table' => 'inventory_item', - 'hashref' => { 'classnum' => $classnum, - 'svcnum' => $old->svcnum, - 'item' => $old->$field(), - }, + 'table' => 'inventory_item', + 'hashref' => { 'classnum' => $classnum, + 'svcnum' => $old->svcnum, + }, + 'extra_sql' => ' AND '. + '( ( svc_field IS NOT NULL AND svc_field = '.$dbh->quote($field).' )'. + ' OR ( svc_field IS NULL AND item = '. dbh->quote($old->$field).' )'. + ')', }); if ( $old_inv ) { $old_inv->svcnum(''); + $old_inv->svc_field(''); my $oerror = $old_inv->replace; if ( $oerror ) { $dbh->rollback if $oldAutoCommit; return "Error unprovisioning inventory: $oerror"; } + } else { + warn "old inventory_item not found for $field ". $self->$field; } } + $inventory_item->svcnum( $self->svcnum ); + $inventory_item->svc_field( $field ); + my $ierror = $inventory_item->replace(); + if ( $ierror ) { + $dbh->rollback if $oldAutoCommit; + return "Error provisioning inventory: $ierror"; + } + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -906,6 +959,7 @@ sub return_inventory { foreach my $inventory_item ( $self->inventory_item ) { $inventory_item->svcnum(''); + $inventory_item->svc_field(''); my $error = $inventory_item->replace(); if ( $error ) { $dbh->rollback if $oldAutoCommit; @@ -996,9 +1050,8 @@ sub export_getsettings { my %defaults = (); my $error = $self->export('getsettings', \%settings, \%defaults); if ( $error ) { - #XXX bubble this up better warn "error running export_getsetings: $error"; - return ( {}, {} ); + return ( { 'error' => $error }, {} ); } ( \%settings, \%defaults ); } @@ -1016,13 +1069,49 @@ sub export_getstatus { my %hash = (); my $error = $self->export('getstatus', \$html, \%hash); if ( $error ) { - #XXX bubble this up better warn "error running export_getstatus: $error"; - return ( '', {} ); + return ( '', { 'error' => $error } ); } ( $html, \%hash ); } +=item export_setstatus + +Runs export_setstatus callbacks. If there is an error, returns the error, +otherwise returns false. + +=cut + +sub export_setstatus { + my( $self, @args ) = @_; + my $error = $self->export('setstatus', @args); + if ( $error ) { + warn "error running export_setstatus: $error"; + return $error; + } + ''; +} + +sub export_setstatus_listadd { + my( $self, @args ) = @_; + my $error = $self->export('setstatus_listadd', @args); + if ( $error ) { + warn "error running export_setstatus: $error"; + return $error; + } + ''; +} + +sub export_setstatus_listdel { + my( $self, @args ) = @_; + my $error = $self->export('setstatus_listdel', @args); + if ( $error ) { + warn "error running export_setstatus: $error"; + return $error; + } + ''; +} + =item export HOOK [ EXPORT_ARGS ] Runs the provided export hook (i.e. "suspend", "unsuspend") for this service.