From 7d64a6acdc011b65b495e9ee4288c86be28d6897 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 8 Nov 2003 16:36:48 +0000 Subject: [PATCH] add order_pkg and cancel_pkg functions to self-service --- FS/FS/ClientAPI/MyAccount.pm | 116 +++++++++++++++++++++++++++++++++++++++++++ FS/FS/cust_main.pm | 35 ++++++++++--- 2 files changed, 144 insertions(+), 7 deletions(-) diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index 6bb664dfe..c9a749424 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -14,6 +14,7 @@ use FS::svc_domain; use FS::cust_main; use FS::cust_bill; use FS::cust_main_county; +use FS::cust_pkg; use FS::ClientAPI; #hmm FS::ClientAPI->register_handlers( @@ -23,6 +24,9 @@ FS::ClientAPI->register_handlers( 'MyAccount/cancel' => \&cancel, 'MyAccount/payment_info' => \&payment_info, 'MyAccount/process_payment' => \&process_payment, + 'MyAccount/list_pkgs' => \&list_pkgs, + 'MyAccount/order_pkg' => \&order_pkg, + 'MyAccount/cancel_pkg' => \&cancel_pkg, ); #store in db? @@ -253,5 +257,117 @@ sub cancel { } +sub list_pkgs { + my $p = shift; + my $session = $cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my $custnum = $session->{'custnum'}; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + return { 'cust_pkg' => [ map { $_->hashref } $cust_main->ncancelled_pkgs ] }; + +} + +sub order_pkg { + my $p = shift; + my $session = $cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my $custnum = $session->{'custnum'}; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + #false laziness w/ClientAPI/Signup.pm + + my $cust_pkg = new FS::cust_pkg ( { + 'custnum' => $custnum, + 'pkgpart' => $p->{'pkgpart'}, + } ); + my $error = $cust_pkg->check; + return { 'error' => $error } if $error; + + my $svc_acct = new FS::svc_acct ( { + 'svcpart' => $p->{'svcpart'} || $cust_pkg->part_pkg->svcpart('svc_acct'), + map { $_ => $p->{$_} } + qw( username _password sec_phrase popnum ), + } ); + + my @acct_snarf; + my $snarfnum = 1; + while ( length($p->{"snarf_machine$snarfnum"}) ) { + my $acct_snarf = new FS::acct_snarf ( { + 'machine' => $p->{"snarf_machine$snarfnum"}, + 'protocol' => $p->{"snarf_protocol$snarfnum"}, + 'username' => $p->{"snarf_username$snarfnum"}, + '_password' => $p->{"snarf_password$snarfnum"}, + } ); + $snarfnum++; + push @acct_snarf, $acct_snarf; + } + $svc_acct->child_objects( \@acct_snarf ); + + my $y = $svc_acct->setdefault; # arguably should be in new method + return { 'error' => $y } if $y && !ref($y); + + $error = $svc_acct->check; + return { 'error' => $error } if $error; + + use Tie::RefHash; + tie my %hash, 'Tie::RefHash'; + %hash = ( $cust_pkg => [ $svc_acct ] ); + #msgcat + $error = $cust_main->order_pkgs( \%hash, '', 'noexport' => 1 ); + return { 'error' => $error } if $error; + + my $conf = new FS::Conf; + if ( $conf->exists('signup_server-realtime') ) { + + my $old_balance = $cust_main->balance; + + my $bill_error = $cust_main->bill; + $cust_main->apply_payments; + $cust_main->apply_credits; + $bill_error = $cust_main->collect; + + if ( $cust_main->balance > $old_balance ) { + $cust_pkg->cancel('quiet'=>1); + return { 'error' => '_decline' }; + } else { + $cust_pkg->reexport; + } + + } else { + $cust_pkg->reexport; + } + + return { error => '' }; + +} + +sub cancel_pkg { + my $p = shift; + my $session = $cache->get($p->{'session_id'}) + or return { 'error' => "Can't resume session" }; #better error message + + my $custnum = $session->{'custnum'}; + + my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) + or return { 'error' => "unknown custnum $custnum" }; + + my $pkgnum = $session->{'pkgnum'}; + + my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum, + 'pkgnum' => $pkgnum, } ) + or return { 'error' => "unknown pkgnum $pkgnum" }; + + my $error = $cust_main->cancel( 'quiet'=>1 ); + return { 'error' => $error }; + +} + 1; diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 2c89bb065..8511e1a45 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -294,8 +294,8 @@ sub insert { } # packages - local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'}; - $error = $self->order_pkgs($cust_pkgs, \$seconds); + #local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'}; + $error = $self->order_pkgs($cust_pkgs, \$seconds, %options); if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; @@ -329,9 +329,27 @@ sub insert { } -=item order_pkgs +=item order_pkgs HASHREF, [ , 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 +method containing FS::cust_pkg and FS::svc_I objects. There should +be a better explanation of this, but until then, here's an example: + + use Tie::RefHash; + tie %hash, 'Tie::RefHash'; #this part is important + %hash = ( + $cust_pkg => [ $svc_acct ], + ... + ); + $cust_main->order_pkgs( \%hash, 'noexport'=>1 ); + +Currently available options are: I -document me. like ->insert(%cust_pkg) on an existing record +If I is set true, no provisioning jobs (exports) are scheduled. +(You can schedule them later with the B method for each +cust_pkg object. Using the B method on the cust_main object is not +recommended, as existing services will also be reexported.) =cut @@ -339,6 +357,7 @@ sub order_pkgs { my $self = shift; my $cust_pkgs = shift; my $seconds = shift; + my %options = @_; local $SIG{HUP} = 'IGNORE'; local $SIG{INT} = 'IGNORE'; @@ -351,6 +370,8 @@ sub order_pkgs { local $FS::UID::AutoCommit = 0; my $dbh = dbh; + local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'}; + foreach my $cust_pkg ( keys %$cust_pkgs ) { $cust_pkg->custnum( $self->custnum ); my $error = $cust_pkg->insert; @@ -379,9 +400,9 @@ sub order_pkgs { =item reexport -document me. Re-schedules all exports by calling the B method -of all associated packages (see L). If there is an error, -returns the error; otherwise returns false. +Re-schedules all exports by calling the B method of all associated +packages (see L). If there is an error, returns the error; +otherwise returns false. =cut -- 2.11.0