diff options
author | ivan <ivan> | 2004-07-15 22:40:01 +0000 |
---|---|---|
committer | ivan <ivan> | 2004-07-15 22:40:01 +0000 |
commit | 6ced9264b8ec79e4b460be90ede25ec72a7dfc16 (patch) | |
tree | 1f55573018ede308c5992be02bc4a81e8fab31a2 /FS | |
parent | 582e73e52fd2f0324e8836ee66ae69e7a82ed364 (diff) |
big update for customer self-service: add provisioning/unprovisioning of purchased services, like fs_selfadmin
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/ClientAPI/MyAccount.pm | 138 | ||||
-rw-r--r-- | FS/FS/ClientAPI/Signup.pm | 2 | ||||
-rw-r--r-- | FS/FS/cust_pkg.pm | 50 |
3 files changed, 185 insertions, 5 deletions
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index f51174e5d..639cb7b9b 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -22,6 +22,7 @@ use FS::cust_pkg; use FS::ClientAPI; #hmm FS::ClientAPI->register_handlers( 'MyAccount/login' => \&login, + 'MyAccount/logout' => \&logout, 'MyAccount/customer_info' => \&customer_info, 'MyAccount/edit_info' => \&edit_info, 'MyAccount/invoice' => \&invoice, @@ -33,6 +34,9 @@ FS::ClientAPI->register_handlers( 'MyAccount/order_pkg' => \&order_pkg, 'MyAccount/cancel_pkg' => \&cancel_pkg, 'MyAccount/charge' => \&charge, + 'MyAccount/part_svc_info' => \&part_svc_info, + 'MyAccount/provision_acct' => \&provision_acct, + 'MyAccount/unprovision_svc' => \&unprovision_svc, ); use vars qw( @cust_main_editable_fields ); @@ -92,6 +96,16 @@ sub login { }; } +sub logout { + my $p = shift; + if ( $p->{'session_id'} ) { + $cache->remove($p->{'session_id'}); + return { 'error' => '' }; + } else { + return { 'error' => "Can't resume session" }; #better error message + } +} + sub customer_info { my $p = shift; @@ -445,7 +459,24 @@ sub list_pkgs { my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ) or return { 'error' => "unknown custnum $custnum" }; - return { 'cust_pkg' => [ map { $_->hashref } $cust_main->ncancelled_pkgs ] }; + #return { 'cust_pkg' => [ map { $_->hashref } $cust_main->ncancelled_pkgs ] }; + + { 'svcnum' => $session->{'svcnum'}, + 'cust_pkg' => [ map { + { $_->hash, + $_->part_pkg->hash, + part_svc => + [ map $_->hashref, $_->available_part_svc ], + cust_svc => + [ map { { $_->hash, + label => [ $_->label ], + } + } $_->cust_svc + ], + }; + } $cust_main->ncancelled_pkgs + ], + }; } @@ -598,5 +629,110 @@ sub cancel_pkg { } +sub provision_acct { + 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 = $p->{'pkgnum'}; + + my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum, + 'pkgnum' => $pkgnum, + } ) + or return { 'error' => "unknown pkgnum $pkgnum" }; + + my $part_svc = qsearchs('part_svc', { 'svcpart' => $p->{'svcpart'} } ) + or return { 'error' => "unknown svcpart $p->{'svcpart'}" }; + + return { 'error' => gettext('passwords_dont_match') } + if $p->{'_password'} ne $p->{'_password2'}; + return { 'error' => gettext('empty_password') } + unless length($p->{'_password'}); + + my $svc_acct = new FS::svc_acct( { + 'pkgnum' => $p->{'pkgnum'}, + 'svcpart' => $p->{'svcpart'}, + 'username' => $p->{'username'}, + '_password' => $p->{'_password'}, + } ); + + return { 'svc' => $part_svc->svc, + 'error' => $svc_acct->insert + }; + +} + +sub part_svc_info { + 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 = $p->{'pkgnum'}; + + my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum, + 'pkgnum' => $pkgnum, + } ) + or return { 'error' => "unknown pkgnum $pkgnum" }; + + my $svcpart = $p->{'svcpart'}; + + my $pkg_svc = qsearchs('pkg_svc', { 'pkgpart' => $cust_pkg->pkgpart, + 'svcpart' => $svcpart, } ) + or return { 'error' => "unknown svcpart $svcpart for pkgnum $pkgnum" }; + my $part_svc = $pkg_svc->part_svc; + + return { + 'svc' => $part_svc->svc, + 'svcdb' => $part_svc->svcdb, + 'pkgnum' => $pkgnum, + 'svcpart' => $svcpart, + + 'security_phrase' => 0, #XXX ! + 'svc_acct_pop' => [], #XXX ! + 'popnum' => '', + 'init_popstate' => '', + 'popac' => '', + 'acstate' => '', + }; + +} + +sub unprovision_svc { + 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 $svcnum = $p->{'svcnum'}; + + my $cust_svc = qsearchs('cust_svc', { 'svcnum' => $svcnum, } ) + or return { 'error' => "unknown svcnum $svcnum" }; + + return { 'error' => "Service $svcnum does not belong to customer $custnum" } + unless $cust_svc->cust_pkg->custnum == $custnum; + + return { 'svc' => $cust_svc->part_svc->svc, + 'error' => $cust_svc->cancel + }; + +} + 1; diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm index 2e2b80fcb..81ed5e65c 100644 --- a/FS/FS/ClientAPI/Signup.pm +++ b/FS/FS/ClientAPI/Signup.pm @@ -128,7 +128,7 @@ sub new_customer { #return "Passwords don't match" # if $hashref->{'_password'} ne $hashref->{'_password2'} return { 'error' => gettext('empty_password') } - unless $packet->{'_password'}; + unless length($packet->{'_password'}); # a bit inefficient for large numbers of pops return { 'error' => gettext('no_access_number_selected') } unless $packet->{'popnum'} || !scalar(qsearch('svc_acct_pop',{} )); diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index fb41dfcf8..d2a48e9f7 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -502,15 +502,22 @@ sub part_pkg { : qsearchs( 'part_pkg', { 'pkgpart' => $self->pkgpart } ); } -=item cust_svc +=item cust_svc [ SVCPART ] Returns the services for this package, as FS::cust_svc objects (see -L<FS::cust_svc>) +L<FS::cust_svc>). If a svcpart is specified, return only the matching +services. =cut sub cust_svc { my $self = shift; + + if ( @_ ) { + return qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum, + 'svcpart' => shift, } ); + } + #if ( $self->{'_svcnum'} ) { # values %{ $self->{'_svcnum'}->cache }; #} else { @@ -524,8 +531,45 @@ sub cust_svc { $pkg_svc ? $pkg_svc->quantity : 0, ]; } - qsearch ( 'cust_svc', { 'pkgnum' => $self->pkgnum } ); + qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } ); #} + +} + +=item num_cust_svc [ SVCPART ] + +Returns the number of provisioned services for this package. If a svcpart is +specified, counts only the matching services. + +=cut + +sub num_cust_svc { + my $self = shift; + my $sql = 'SELECT COUNT(*) FROM cust_svc WHERE pkgnum = ?'; + $sql .= ' AND svcpart = ?' if @_; + my $sth = dbh->prepare($sql) or die dbh->errstr; + $sth->execute($self->pkgnum, @_) or die $sth->errstr; + $sth->fetchrow_arrayref->[0]; +} + +=item available_part_svc + +Returns a list FS::part_svc objects representing services included in this +package but not yet provisioned. Each FS::part_svc object also has an extra +field, I<num_avail>, which specifies the number of available services. + +=cut + +sub available_part_svc { + my $self = shift; + grep { $_->num_avail > 0 } + map { + my $part_svc = $_->part_svc; + $part_svc->{'Hash'}{'num_avail'} = #evil encapsulation-breaking + $_->quantity - $self->num_cust_svc($_->svcpart); + $part_svc; + } + $self->part_pkg->pkg_svc; } =item labels |