use Tie::RefHash;
use FS::Conf;
use FS::Record qw(qsearch qsearchs dbdef);
+use FS::Msgcat qw(gettext);
use FS::agent;
use FS::cust_main_county;
use FS::part_pkg;
use FS::cust_pkg;
use FS::svc_acct;
use FS::acct_snarf;
-use FS::Msgcat qw(gettext);
+use FS::queue;
use FS::ClientAPI; #hmm
FS::ClientAPI->register_handlers(
my @acct_snarf;
my $snarfnum = 1;
- while ( length($packet->{"snarf_machine$snarfnum"}) ) {
+ while ( exists($packet->{"snarf_machine$snarfnum"})
+ && length($packet->{"snarf_machine$snarfnum"}) ) {
my $acct_snarf = new FS::acct_snarf ( {
'machine' => $packet->{"snarf_machine$snarfnum"},
'protocol' => $packet->{"snarf_protocol$snarfnum"},
$error = $svc_acct->check;
return { 'error' => $error } if $error;
+ #setup a job dependancy to delay provisioning
+ my $placeholder = new FS::queue ( {
+ 'job' => 'FS::ClientAPI::Signup::__placeholder',
+ 'status' => 'locked',
+ } );
+ $error = $placeholder->insert;
+ return { 'error' => $error } if $error;
+
use Tie::RefHash;
tie my %hash, 'Tie::RefHash';
%hash = ( $cust_pkg => [ $svc_acct ] );
#msgcat
- $error = $cust_main->insert( \%hash, \@invoicing_list, 'noexport' => 1 );
- return { 'error' => $error } if $error;
+ $error = $cust_main->insert(
+ \%hash,
+ \@invoicing_list,
+ 'depend_jobnum' => $placeholder->jobnum,
+ );
+ if ( $error ) {
+ my $perror = $placeholder->delete;
+ $error .= " (Additionally, error removing placeholder: $perror)" if $perror;
+ return { 'error' => $error };
+ }
if ( $conf->exists('signup_server-realtime') ) {
local $FS::svc_Common::noexport_hack = 1;
$cust_main->cancel('quiet'=>1);
+ my $perror = $placeholder->depended_delete;
+ warn "error removing provisioning jobs after decline: $perror" if $perror;
+ unless ( $perror ) {
+ $perror = $placeholder->delete;
+ warn "error removing placeholder after decline: $perror" if $perror;
+ }
+
return { 'error' => '_decline' };
}
}
- $cust_main->reexport;
+
+ $error = $placeholder->delete;
+ return { 'error' => $error } if $error;
return { error => '' };
package FS::cust_main;
use strict;
-use vars qw( @ISA $conf $Debug $import );
+use vars qw( @ISA $conf $DEBUG $import );
use vars qw( $realtime_bop_decline_quiet ); #ugh
use Safe;
use Carp;
$realtime_bop_decline_quiet = 0;
-$Debug = 0;
-#$Debug = 1;
+$DEBUG = 0;
+#$DEBUG = 1;
$import = 0;
$cust_main->insert( {}, [ $email, 'POST' ] );
-Currently available options are: I<noexport>
+Currently available options are: I<depend_jobnum> and I<noexport>.
-If I<noexport> is set true, no provisioning jobs (exports) are scheduled.
-(You can schedule them later with the B<reexport> method.)
+If I<depend_jobnum> is set, all provisioning jobs will have a dependancy
+on the supplied jobnum (they will not run until the specific job completes).
+This can be used to defer provisioning until some action completes (such
+as running the customer's credit card sucessfully).
+
+The I<noexport> option is deprecated. If I<noexport> is set true, no
+provisioning jobs (exports) are scheduled. (You can schedule them later with
+the B<reexport> method.)
=cut
my $cust_pkgs = @_ ? shift : {};
my $invoicing_list = @_ ? shift : '';
my %options = @_;
+ warn "FS::cust_main::insert called with options ".
+ join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
+ if $DEBUG;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
}
# packages
- #local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'};
$error = $self->order_pkgs($cust_pkgs, \$seconds, %options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
}
-=item order_pkgs HASHREF, [ , OPTION => VALUE ... ] ]
+=item order_pkgs HASHREF, [ SECONDSREF, [ , OPTION => VALUE ... ] ]
Like the insert method on an existing record, this method orders a package
and included services atomicaly. Pass a Tie::RefHash data structure to this
$cust_pkg => [ $svc_acct ],
...
);
- $cust_main->order_pkgs( \%hash, 'noexport'=>1 );
+ $cust_main->order_pkgs( \%hash, \'0', 'noexport'=>1 );
+
+Currently available options are: I<depend_jobnum> and I<noexport>.
-Currently available options are: I<noexport>
+If I<depend_jobnum> is set, all provisioning jobs will have a dependancy
+on the supplied jobnum (they will not run until the specific job completes).
+This can be used to defer provisioning until some action completes (such
+as running the customer's credit card sucessfully).
-If I<noexport> is set true, no provisioning jobs (exports) are scheduled.
-(You can schedule them later with the B<reexport> method for each
-cust_pkg object. Using the B<reexport> method on the cust_main object is not
-recommended, as existing services will also be reexported.)
+The I<noexport> option is deprecated. If I<noexport> is set true, no
+provisioning jobs (exports) are scheduled. (You can schedule them later with
+the B<reexport> method for each cust_pkg object. Using the B<reexport> method
+on the cust_main object is not recommended, as existing services will also be
+reexported.)
=cut
my $cust_pkgs = shift;
my $seconds = shift;
my %options = @_;
+ my %svc_options = ();
+ $svc_options{'depend_jobnum'} = $options{'depend_jobnum'}
+ if exists $options{'depend_jobnum'};
+ warn "FS::cust_main::order_pkgs called with options ".
+ join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
+ if $DEBUG;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
$svc_something->seconds( $svc_something->seconds + $$seconds );
$$seconds = 0;
}
- $error = $svc_something->insert;
+ $error = $svc_something->insert(%svc_options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
#return "inserting svc_ (transaction rolled back): $error";
=item reexport
+This method is deprecated. See the I<depend_jobnum> option to the insert and
+order_pkgs methods for a better way to defer provisioning.
+
Re-schedules all exports by calling the B<reexport> method of all associated
packages (see L<FS::cust_pkg>). If there is an error, returns the error;
otherwise returns false.
sub reexport {
my $self = shift;
+ carp "warning: FS::cust_main::reexport is deprectated; ".
+ "use the depend_jobnum option to insert or order_pkgs to delay export";
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
my $dbh = dbh;
my $balance = $self->balance;
- warn "collect customer". $self->custnum. ": balance $balance" if $Debug;
+ warn "collect customer". $self->custnum. ": balance $balance" if $DEBUG;
unless ( $balance > 0 ) { #redundant?????
$dbh->rollback if $oldAutoCommit; #hmm
return '';
last if $self->balance <= 0;
warn "invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ")"
- if $Debug;
+ if $DEBUG;
foreach my $part_bill_event (
sort { $a->seconds <=> $b->seconds
|| $self->balance <= 0; # or if balance<=0
warn "calling invoice event (". $part_bill_event->eventcode. ")\n"
- if $Debug;
+ if $DEBUG;
my $cust_main = $self; #for callback
my $error;
sub realtime_bop {
my( $self, $method, $amount, %options ) = @_;
- if ( $Debug ) {
+ if ( $DEBUG ) {
warn "$self $method $amount\n";
warn " $_ => $options{$_}\n" foreach keys %options;
}
=item reexport
+This method is deprecated. See the I<depend_jobnum> option to the insert and
+order_pkgs methods in FS::cust_main for a better way to defer provisioning.
+
=cut
sub reexport {
package FS::queue;
use strict;
-use vars qw( @ISA @EXPORT_OK $conf $jobnums);
+use vars qw( @ISA @EXPORT_OK $DEBUG $conf $jobnums);
use Exporter;
use FS::UID;
use FS::Conf;
@ISA = qw(FS::Record);
@EXPORT_OK = qw( joblisting );
+$DEBUG = 0;
+#$DEBUG = 1;
+
$FS::UID::callback{'FS::queue'} = sub {
$conf = new FS::Conf;
};
}
}
- push @$jobnums, $self->jobnum if $jobnums;
+ if ( $jobnums ) {
+ warn "jobnums global is active: $jobnums\n" if $DEBUG;
+ push @$jobnums, $self->jobnum;
+ }
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
=item queue_depend
Returns the FS::queue_depend objects associated with this job, if any.
+(Dependancies that must complete before this job can be run).
=cut
qsearch('queue_depend', { 'jobnum' => $self->jobnum } );
}
-
=item depend_insert OTHER_JOBNUM
Inserts a dependancy for this job - it will not be run until the other job
$queue_depend->insert;
}
+=item queue_depended
+
+Returns the FS::queue_depend objects that associate other jobs with this job,
+if any. (The jobs that are waiting for this job to complete before they can
+run).
+
+=cut
+
+sub queue_depended {
+ my $self = shift;
+ qsearch('queue_depend', { 'depend_jobnum' => $self->jobnum } );
+}
+
+=item depended_delete
+
+Deletes the other queued jobs (FS::queue objects) that are waiting for this
+job, if any. If there is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub depended_delete {
+ my $self = shift;
+ my $error;
+ foreach my $job (
+ map { qsearchs('queue', { 'jobnum' => $_->jobnum } ) } $self->queue_depended
+ ) {
+ $error = $job->depended_delete;
+ return $error if $error;
+ $error = $job->delete;
+ return $error if $error
+ }
+}
+
=back
=head1 SUBROUTINES
=head1 VERSION
-$Id: queue.pm,v 1.16 2003-08-05 00:20:46 khoff Exp $
+$Id: queue.pm,v 1.17 2004-03-03 13:42:08 ivan Exp $
=head1 BUGS
package FS::svc_Common;
use strict;
-use vars qw( @ISA $noexport_hack );
+use vars qw( @ISA $noexport_hack $DEBUG );
use FS::Record qw( qsearch qsearchs fields dbh );
use FS::cust_svc;
use FS::part_svc;
@ISA = qw( FS::Record );
+$DEBUG = 0;
+#$DEBUG = 1;
+
=head1 NAME
FS::svc_Common - Object method for all svc_ records
$self->SUPER::check;
}
-=item insert [ JOBNUM_ARRAYREF [ OBJECTS_ARRAYREF ] ]
+=item insert [ , OPTION => VALUE ... ]
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
defined. An FS::cust_svc record will be created and inserted.
-If an arrayref is passed as parameter, the B<jobnum>s of any export jobs will
-be added to the array.
+Currently available options are: I<jobnums>, I<child_objects> and
+I<depend_jobnum>.
+
+If I<jobnum> is set to an array reference, the jobnums of any export jobs will
+be added to the referenced array.
+
+If I<child_objects> is set to an array reference of FS::tablename objects (for
+example, FS::acct_snarf objects), they will have their svcnum fieldsset and
+will be inserted after this record, but before any exports are run.
-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.
+If I<depend_jobnum> 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)).
=cut
sub insert {
my $self = shift;
- local $FS::queue::jobnums = shift if @_;
- my $objects = scalar(@_) ? shift : [];
+ my %options = @_;
+ warn "FS::svc_Common::insert called with options ".
+ join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
+ if $DEBUG;
+
+ my @jobnums = ();
+ local $FS::queue::jobnums = \@jobnums;
+ warn "FS::svc_Common::insert: set \$FS::queue::jobnums to $FS::queue::jobnums"
+ if $DEBUG;
+ my $objects = $options{'child_objects'} || [];
+ my $depend_jobnums = $options{'depend_jobnum'} || [];
+ $depend_jobnums = [ $depend_jobnums ] unless ref($depend_jobnums);
my $error;
local $SIG{HUP} = 'IGNORE';
#new-style exports!
unless ( $noexport_hack ) {
+
+ warn "FS::svc_Common::insert: \$FS::queue::jobnums is $FS::queue::jobnums"
+ if $DEBUG;
+
foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
my $error = $part_export->export_insert($self);
if ( $error ) {
" (transaction rolled back): $error";
}
}
+
+ foreach my $depend_jobnum ( @$depend_jobnums ) {
+ warn "inserting dependancies on supplied job $depend_jobnum\n"
+ if $DEBUG;
+ foreach my $jobnum ( @jobnums ) {
+ my $queue = qsearchs('queue', { 'jobnum' => $jobnum } );
+ warn "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";
+ }
+ }
+ }
+
+ }
+
+ if ( exists $options{'jobnums'} ) {
+ push @{ $options{'jobnums'} }, @jobnums;
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
@ISA = qw( FS::svc_Common );
$DEBUG = 0;
+#$DEBUG = 1;
$me = '[FS::svc_acct]';
#ask FS::UID to run this stuff for us later
sub table { 'svc_acct'; }
-=item insert
+=item insert [ , OPTION => VALUE ... ]
Adds this account to the database. If there is an error, returns the error,
otherwise returns false.
svcnum fields set and will be inserted after this record, but before any
exports are run.
+Currently available options are: I<depend_jobnum>
+
+If I<depend_jobnum> 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)).
+
(TODOC: L<FS::queue> and L<freeside-queued>)
(TODOC: new exports!)
-
=cut
sub insert {
my $self = shift;
+ my %options = @_;
my $error;
local $SIG{HUP} = 'IGNORE';
#see? i told you it was more complicated
my @jobnums;
- $error = $self->SUPER::insert(\@jobnums, $self->child_objects || [] );
+ $error = $self->SUPER::insert(
+ 'jobnums' => \@jobnums,
+ 'child_objects' => $self->child_objects,
+ %options,
+ );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
return "error queuing welcome email: $error";
}
+ if ( $options{'depend_jobnum'} ) {
+ warn "$me depend_jobnum found; adding to welcome email dependancies"
+ if $DEBUG;
+ if ( ref($options{'depend_jobnum'}) ) {
+ warn "$me adding jobs ". join(', ', @{$options{'depend_jobnum'}} ).
+ "to welcome email dependancies"
+ if $DEBUG;
+ push @jobnums, @{ $options{'depend_jobnum'} };
+ } else {
+ warn "$me adding job $options{'depend_jobnum'} ".
+ "to welcome email dependancies"
+ if $DEBUG;
+ push @jobnums, $options{'depend_jobnum'};
+ }
+ }
+
foreach my $jobnum ( @jobnums ) {
my $error = $wqueue->depend_insert($jobnum);
if ( $error ) {
radius_usergroup_selector? putting web ui components in here? they should
probably live somewhere else...
+insertion of RADIUS group stuff in insert could be done with child_objects now
+(would probably clean up export of them too)
+
=head1 SEE ALSO
L<FS::svc_Common>, edit/part_svc.cgi from an installed web interface,
sub table { 'svc_broadband'; }
-=item insert
+=item insert [ , OPTION => VALUE ... ]
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
The additional fields pkgnum and svcpart (see FS::cust_svc) should be
defined. An FS::cust_svc record will be created and inserted.
+Currently available options are: I<depend_jobnum>
+
+If I<depend_jobnum> 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)).
+
=cut
# Standard FS::svc_Common::insert
sub table { 'svc_domain'; }
-=item insert
+=item insert [ , OPTION => VALUE ... ]
Adds this domain to the database. If there is an error, returns the error,
otherwise returns false.
appropriate records are added to the domain_record table (see
L<FS::domain_record>).
+Currently available options are: I<depend_jobnum>
+
+If I<depend_jobnum> 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)).
+
=cut
sub insert {
return "Domain not found (see whois)";
}
- $error = $self->SUPER::insert;
+ $error = $self->SUPER::insert(@_);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
sub table { 'svc_external'; }
-=item insert
+=item insert [ , OPTION => VALUE ... ]
Adds this external service to the database. If there is an error, returns the
error, otherwise returns false.
The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
defined. An FS::cust_svc record will be created and inserted.
-=cut
+Currently available options are: I<depend_jobnum>
-sub insert {
- my $self = shift;
- my $error;
+If I<depend_jobnum> 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)).
- $error = $self->SUPER::insert;
- return $error if $error;
+=cut
- '';
-}
+#sub insert {
+# my $self = shift;
+# my $error;
+#
+# $error = $self->SUPER::insert(@_);
+# return $error if $error;
+#
+# '';
+#}
=item delete
=cut
-sub delete {
- my $self = shift;
- my $error;
-
- $error = $self->SUPER::delete;
- return $error if $error;
-
- '';
-}
+#sub delete {
+# my $self = shift;
+# my $error;
+#
+# $error = $self->SUPER::delete;
+# return $error if $error;
+#
+# '';
+#}
=item replace OLD_RECORD
=cut
-sub replace {
- my ( $new, $old ) = ( shift, shift );
- my $error;
-
- $error = $new->SUPER::replace($old);
- return $error if $error;
-
- '';
-}
+#sub replace {
+# my ( $new, $old ) = ( shift, shift );
+# my $error;
+#
+# $error = $new->SUPER::replace($old);
+# return $error if $error;
+#
+# '';
+#}
=item suspend
sub table { 'svc_forward'; }
-=item insert
+=item insert [ , OPTION => VALUE ... ]
Adds this mail forwarding alias to the database. If there is an error, returns
the error, otherwise returns false.
The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
defined. An FS::cust_svc record will be created and inserted.
+Currently available options are: I<depend_jobnum>
+
+If I<depend_jobnum> 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)).
+
=cut
sub insert {
$error = $self->check;
return $error if $error;
- $error = $self->SUPER::insert;
+ $error = $self->SUPER::insert(@_);
if ($error) {
$dbh->rollback if $oldAutoCommit;
return $error;
sub table { 'svc_www'; }
-=item insert
+=item insert [ , OPTION => VALUE ... ]
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
defined. An FS::cust_svc record will be created and inserted.
+Currently available options are: I<depend_jobnum>
+
+If I<depend_jobnum> 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)).
+
+
=cut
sub insert {
$self->recnum($domain_record->recnum);
}
- $error = $self->SUPER::insert;
+ $error = $self->SUPER::insert(@_);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;