X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fsvc_Common.pm;h=5c6e16b826b1ddf74ce3b1e59eb844b4cccfdc46;hb=f9a181e4c2e505df84de16190ee3b75011326f3f;hp=8cbcc91bb17ad22c27835117a46bd3181f78cad9;hpb=2b11588f2aa418719decb2ef501b1762cede4385;p=freeside.git diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index 8cbcc91bb..5c6e16b82 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -330,6 +330,8 @@ sub preinsert_hook_first { ''; } sub _check_duplcate { ''; } sub preinsert_hook { ''; } sub table_dupcheck_fields { (); } +sub predelete_hook { ''; } +sub predelete_hook_first { ''; } =item delete [ , OPTION => VALUE ... ] @@ -356,9 +358,11 @@ sub delete { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - my $error = $self->SUPER::delete + my $error = $self->predelete_hook_first + || $self->SUPER::delete || $self->export('delete', @$export_args) || $self->return_inventory + || $self->predelete_hook || $self->cust_svc->delete ; if ( $error ) { @@ -371,11 +375,54 @@ sub delete { ''; } +=item expire DATE + +Currently this will only run expire exports if any are attached + +=cut + +sub expire { + my($self,$date) = (shift,shift); + + return 'Expire date must be specified' unless $date; + + 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 $export_args = [$date]; + my $error = $self->export('expire', @$export_args); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + ''; +} + =item replace [ OLD_RECORD ] [ HASHREF | OPTION => VALUE ] Replaces OLD_RECORD with this one. If there is an error, returns the error, otherwise returns false. +Currently available options are: I and I. + +If I is set (to a scalar jobnum or an array reference of +jobnums), all provisioning jobs will have a dependancy on the supplied +jobnum(s) (they will not run until the specific job(s) complete(s)). + +If I is set to an array reference, the referenced list will be +passed to export commands. + =cut sub replace { @@ -390,6 +437,13 @@ sub replace { ? shift : { @_ }; + my @jobnums = (); + local $FS::queue::jobnums = \@jobnums; + warn "[$me] replace: set \$FS::queue::jobnums to $FS::queue::jobnums\n" + if $DEBUG; + my $depend_jobnums = $options->{'depend_jobnum'} || []; + $depend_jobnums = [ $depend_jobnums ] unless ref($depend_jobnums); + local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; local $SIG{QUIT} = 'IGNORE'; @@ -401,7 +455,7 @@ sub replace { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - my $error = $new->set_auto_inventory; + my $error = $new->set_auto_inventory($old); if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; @@ -435,6 +489,9 @@ sub replace { #new-style exports! unless ( $noexport_hack ) { + warn "[$me] replace: \$FS::queue::jobnums is $FS::queue::jobnums\n" + if $DEBUG; + my $export_args = $options->{'export_args'} || []; #not quite false laziness, but same pattern as FS::svc_acct::replace and @@ -483,6 +540,21 @@ sub replace { } } + foreach my $depend_jobnum ( @$depend_jobnums ) { + warn "[$me] inserting dependancies on supplied job $depend_jobnum\n" + if $DEBUG; + foreach my $jobnum ( @jobnums ) { + my $queue = qsearchs('queue', { 'jobnum' => $jobnum } ); + warn "[$me] inserting dependancy for job $jobnum on $depend_jobnum\n" + if $DEBUG; + my $error = $queue->depend_insert($depend_jobnum); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error queuing job dependancy: $error"; + } + } + } + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -694,6 +766,7 @@ If there is an error, returns the error, otherwise returns false. sub set_auto_inventory { my $self = shift; + my $old = @_ ? shift : ''; my $error = $self->ut_numbern('svcnum') @@ -734,10 +807,17 @@ sub set_auto_inventory { $hash{'item'} = $self->getfield($field); } + my $agentnums_sql = $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null' => 1, + 'table' => 'inventory_item', + ); + my $inventory_item = qsearchs({ 'table' => 'inventory_item', 'hashref' => \%hash, - 'extra_sql' => 'LIMIT 1 FOR UPDATE', + 'extra_sql' => "AND $agentnums_sql", + 'order_by' => 'ORDER BY ( agentnum IS NULL ) '. #agent inventory first + ' LIMIT 1 FOR UPDATE', }); unless ( $inventory_item ) { @@ -762,6 +842,24 @@ sub set_auto_inventory { 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(), + }, + }); + if ( $old_inv ) { + $old_inv->svcnum(''); + my $oerror = $old_inv->replace; + if ( $oerror ) { + $dbh->rollback if $oldAutoCommit; + return "Error unprovisioning inventory: $oerror"; + } + } + } + } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -987,6 +1085,42 @@ sub clone_kludge_unsuspend { shift; } +=item find_duplicates MODE FIELDS... + +Method used by _check_duplicate routines to find services with duplicate +values in specified fields. Set MODE to 'global' to search across all +services, or 'export' to limit to those that share one or more exports +with this service. FIELDS is a list of field names; only services +matching in all fields will be returned. Empty fields will be skipped. + +=cut + +sub find_duplicates { + my $self = shift; + my $mode = shift; + my @fields = @_; + + my %search = map { $_ => $self->getfield($_) } + grep { length($self->getfield($_)) } @fields; + return () if !%search; + my @dup = grep { ! $self->svcnum or $_->svcnum != $self->svcnum } + qsearch( $self->table, \%search ); + return () if !@dup; + return @dup if $mode eq 'global'; + die "incorrect find_duplicates mode '$mode'" if $mode ne 'export'; + + my $exports = FS::part_export::export_info($self->table); + my %conflict_svcparts; + my $part_svc = $self->part_svc; + foreach my $part_export ( $part_svc->part_export ) { + %conflict_svcparts = map { $_->svcpart => 1 } $part_export->export_svc; + } + return grep { $conflict_svcparts{$_->cust_svc->svcpart} } @dup; +} + + + + =back =head1 BUGS