diff options
-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 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/SelfService.pm | 42 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/agent.cgi | 4 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/delete_svc.html | 18 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/logout.html | 5 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/make_payment.html | 7 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/myaccount.html | 9 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/myaccount_menu.html | 13 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/payment_results.html | 7 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/process_svc_acct.html | 14 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/provision.html | 77 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html | 66 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 92 | ||||
-rw-r--r-- | fs_selfservice/FS-SelfService/cgi/view_invoice.html | 9 | ||||
-rwxr-xr-x | httemplate/view/cust_main.cgi | 40 |
17 files changed, 527 insertions, 66 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 diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm index 2cda9fe2d..ae6d37671 100644 --- a/fs_selfservice/FS-SelfService/SelfService.pm +++ b/fs_selfservice/FS-SelfService/SelfService.pm @@ -22,17 +22,21 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'chfn' => 'passwd/passwd', 'chsh' => 'passwd/passwd', 'login' => 'MyAccount/login', + 'logout' => 'MyAccount/logout', 'customer_info' => 'MyAccount/customer_info', - 'edit_info' => 'MyAccount/edit_info', + 'edit_info' => 'MyAccount/edit_info', #add to ss cgi! 'invoice' => 'MyAccount/invoice', - 'list_invoices' => 'MyAccount/list_invoices', - 'cancel' => 'MyAccount/cancel', + 'list_invoices' => 'MyAccount/list_invoices', #? + 'cancel' => 'MyAccount/cancel', #add to ss cgi! 'payment_info' => 'MyAccount/payment_info', 'process_payment' => 'MyAccount/process_payment', - 'list_pkgs' => 'MyAccount/list_pkgs', - 'order_pkg' => 'MyAccount/order_pkg', - 'cancel_pkg' => 'MyAccount/cancel_pkg', - 'charge' => 'MyAccount/charge', + 'list_pkgs' => 'MyAccount/list_pkgs', #add to ss cgi! + 'order_pkg' => 'MyAccount/order_pkg', #add to ss cgi! + 'cancel_pkg' => 'MyAccount/cancel_pkg', #add to ss cgi! + 'charge' => 'MyAccount/charge', #? + 'part_svc_info' => 'MyAccount/part_svc_info', + 'provision_acct' => 'MyAccount/provision_acct', + 'unprovision_svc' => 'MyAccount/unprovision_svc', 'signup_info' => 'Signup/signup_info', 'new_customer' => 'Signup/new_customer', 'agent_login' => 'Agent/agent_login', @@ -466,9 +470,28 @@ Returns a hash reference containing customer package information. The hash refe =over 4 + =item cust_pkg HASHREF -Array reference of hash references, each of which has the fields of a cust_pkg record (see L<FS::cust_pkg>). Note these are not FS::cust_pkg objects, but hash references of columns and values. +Array reference of hash references, each of which has the fields of a cust_pkg +record (see L<FS::cust_pkg>) as well as the fields below. Note these are not +the internal FS:: objects, but hash references of columns and values. + +=item all fields of part_pkg (XXXpare this down to a secure subset) + +=item part_svc - An array of hash references, each of which has the following keys: + +=over 4 + +=item all fields of part_svc (XXXpare this down to a secure subset) + +=item avail + +=back + +=item error + +Empty on success, or an error message on errors. =back @@ -1033,7 +1056,8 @@ END =head1 RESELLER FUNCTIONS Note: Resellers can also use the B<signup_info> and B<new_customer> functions -with their active session. +with their active session, and the B<customer_info> and B<order_pkg> functions +with their active session and an additonal I<custnum> parameter. =over 4 diff --git a/fs_selfservice/FS-SelfService/cgi/agent.cgi b/fs_selfservice/FS-SelfService/cgi/agent.cgi index 2d948e790..6d2fd5840 100644 --- a/fs_selfservice/FS-SelfService/cgi/agent.cgi +++ b/fs_selfservice/FS-SelfService/cgi/agent.cgi @@ -221,6 +221,10 @@ sub process_order_pkg { my $results = ''; + unless ( length($cgi->param('_password')) ) { + my $init_data = signup_info( 'session_id' => $session_id ); + $results = { 'error' => $init_data->{msgcat}{empty_password} } + } if ( $cgi->param('_password') ne $cgi->param('_password2') ) { my $init_data = signup_info( 'session_id' => $session_id ); $results = { error => $init_data->{msgcat}{passwords_dont_match} }; diff --git a/fs_selfservice/FS-SelfService/cgi/delete_svc.html b/fs_selfservice/FS-SelfService/cgi/delete_svc.html new file mode 100644 index 000000000..16054a77c --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/delete_svc.html @@ -0,0 +1,18 @@ +<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> +<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> +<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> + +<%= if ( $error ) { + $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error: $error</FONT>!; +} else { + $OUT .= "<FONT SIZE=4>$svc removed.</FONT>"; +} %> + +</TD></TR></TABLE> +<HR> +<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT> +</BODY></HTML> + diff --git a/fs_selfservice/FS-SelfService/cgi/logout.html b/fs_selfservice/FS-SelfService/cgi/logout.html new file mode 100644 index 000000000..0e774e9eb --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/logout.html @@ -0,0 +1,5 @@ +<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> +<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> +You have been logged out. +</BODY></HTML> + diff --git a/fs_selfservice/FS-SelfService/cgi/make_payment.html b/fs_selfservice/FS-SelfService/cgi/make_payment.html index cf6d62e22..3522c0867 100644 --- a/fs_selfservice/FS-SelfService/cgi/make_payment.html +++ b/fs_selfservice/FS-SelfService/cgi/make_payment.html @@ -1,10 +1,9 @@ <HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> <BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> <%= $url = "$selfurl?session=$session_id;action="; ''; %> -<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd"> -<A HREF="<%= $url %>myaccount">MyAccount</A><BR> -<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> --> -</TD><TD VALIGN="top"> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> <FONT SIZE=4>Make a payment</FONT><BR><BR> <FORM NAME="OneTrueForm" METHOD="POST" ACTION="<%=$selfurl%>" onSubmit="document.OneTrueForm.process.disabled=true"> <INPUT TYPE="hidden" NAME="session" VALUE="<%=$session_id%>"> diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount.html b/fs_selfservice/FS-SelfService/cgi/myaccount.html index f48fdedea..9997d7059 100644 --- a/fs_selfservice/FS-SelfService/cgi/myaccount.html +++ b/fs_selfservice/FS-SelfService/cgi/myaccount.html @@ -1,10 +1,9 @@ <HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> <BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> <%= $url = "$selfurl?session=$session_id;action="; ''; %> -<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd"> -<A HREF="<%= $url %>myaccount">MyAccount</A><BR> -<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> --> -</TD><TD VALIGN="top"> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> Hello <%= $name %>!<BR><BR> <%= $small_custview %> @@ -15,7 +14,7 @@ Hello <%= $name %>!<BR><BR> <%= if ( @open_invoices ) { $OUT .= '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#eeeeee">'. - '<TR><TH BGCOLOR="#ff3333" COLSPAN=5>Open Invoices</TH><TD>'; + '<TR><TH BGCOLOR="#ff6666" COLSPAN=5>Open Invoices</TH></TR>'; my $link = qq!<A HREF="<%= $url %>myaccount!; my $col1 = "ffffff"; my $col2 = "dddddd"; diff --git a/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html new file mode 100644 index 000000000..ba3b3f2ff --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/myaccount_menu.html @@ -0,0 +1,13 @@ +<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd"> + +<A HREF="<%= $url %>myaccount">Overview</A><BR><BR> +<!--A HREF="<%= $url %>change_bill"-->Change payment info</A> *<BR><BR> +<!--A HREF="<%= $url %>change_ship"-->Change service address</A> *<BR><BR> +<A HREF="<%= $url %>provision">Setup my services</A><BR><BR> +<!--A HREF="<%= $url %>order"-->Purchase additional package</A> *<BR><BR> +<!--<A HREF="<%= $url %>pw_list">Change password(s)</A> *<BR><BR>--> +<A HREF="passwd.html">Change password(s)</A><BR><BR> +<A HREF="<%= $url %>logout">Logout</A><BR><BR> +* coming soon +</TD> diff --git a/fs_selfservice/FS-SelfService/cgi/payment_results.html b/fs_selfservice/FS-SelfService/cgi/payment_results.html index 92c8cf51b..44289deba 100644 --- a/fs_selfservice/FS-SelfService/cgi/payment_results.html +++ b/fs_selfservice/FS-SelfService/cgi/payment_results.html @@ -1,10 +1,9 @@ <HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> <BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> <%= $url = "$selfurl?session=$session_id;action="; ''; %> -<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd"> -<A HREF="<%= $url %>myaccount">MyAccount</A><BR> -<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> --> -</TD><TD VALIGN="top"> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> <FONT SIZE=4>Payment results</FONT><BR><BR> <%= if ( $error ) { $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error processing your payment: $error</FONT>!; diff --git a/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html b/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html new file mode 100644 index 000000000..7052059c4 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/process_svc_acct.html @@ -0,0 +1,14 @@ +<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> +<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> +<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> + +<FONT SIZE=4><%= $svc %> setup sucessfully.</FONT> + +</TD></TR></TABLE> +<HR> +<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT> +</BODY></HTML> + diff --git a/fs_selfservice/FS-SelfService/cgi/provision.html b/fs_selfservice/FS-SelfService/cgi/provision.html new file mode 100644 index 000000000..326f90229 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/provision.html @@ -0,0 +1,77 @@ +<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> +<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> +<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> +<FONT SIZE=4>Setup services</FONT><BR><BR> + +<SCRIPT> +function areyousure(href, message) { + if (confirm(message) == true) + window.location.href = href; +} +</SCRIPT> + +<%= foreach my $pkg ( + grep { scalar(@{$_->{part_svc}}) + || scalar(@{$_->{cust_svc}}) + } @cust_pkg + ) { + + $OUT .= '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#ffffff">'. + '<TR><TH BGCOLOR="#6666ff" COLSPAN=3>'. + $pkg->{'pkg'}. + '</TH></TR>'; + + my $col1 = "ffffff"; + my $col2 = "dddddd"; + my $col = $col1; + + foreach my $cust_svc ( @{ $pkg->{cust_svc} } ) { + my $td = qq!<TD BGCOLOR="#$col"!; + + $OUT .= '<TR>'. + "$td ALIGN=right>". $cust_svc->{label}[0]. ': </TD>'. + "$td><B>". $cust_svc->{label}[1]. '</B></TD>'. + "$td><FONT SIZE=-1>"; + + #if ( $cust_svc->{label}[2] eq 'svc_acct' ) { + # $OUT .= qq!(<A HREF="${url}changepw;svcnum=$cust_svc->{'svcnum'}">!. + # 'change pw) '; + #} + + unless ( $cust_svc->{'svcnum'} == $svcnum ) { + $OUT .= qq!(<A HREF="javascript:areyousure('${url}delete_svc;svcnum=$cust_svc->{svcnum}', 'This will perminantly delete the $cust_svc->{label}[1] $cust_svc->{label}[0]. Are you sure?')">!. + 'delete</A>)'; + + } + $OUT .= '</FONT></TD></TR>'; + $col = $col eq $col1 ? $col2 : $col1; + } + + $OUT .= '<TR><TD COLSPAN=3 BGCOLOR="#000000"></TD></TR>' + if scalar(@{$pkg->{part_svc}}) && scalar(@{$pkg->{cust_svc}}); + + my $col = $col1; + + foreach my $part_svc ( @{ $pkg->{part_svc} } ) { + + my $td = qq!<TD BGCOLOR="#$col"!; + + $OUT .= "<TR>$td COLSPAN=3>". + qq!<A HREF="${url}provision_svc;pkgnum=$pkg->{'pkgnum'};svcpart=$part_svc->{'svcpart'}">!. + 'Setup '. $part_svc->{'svc'}. '</A> '. + '('. $part_svc->{'num_avail'}. ' available)'. + '</TD></TR>'; + $col = $col eq $col1 ? $col2 : $col1; + } + + $OUT .= '</TABLE><BR>'; + +} %> + +</TD></TR></TABLE> +<HR> +<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT> +</BODY></HTML> diff --git a/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html b/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html new file mode 100644 index 000000000..d18375c82 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/provision_svc_acct.html @@ -0,0 +1,66 @@ +<HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> +<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> +<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> +<FONT SIZE=4>Setup <%= $svc %></FONT><BR><BR> + +<%= if ( $error ) { + $OUT .= qq!<FONT SIZE="+1" COLOR="#ff0000">Error setting up $svc: $error!. + '</FONT><BR><BR>'; +} ''; %> +<FORM ACTION="<%= $selfurl %>" METHOD=POST> +<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>"> +<INPUT TYPE="hidden" NAME="action" VALUE="process_svc_acct"> +<INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%= $pkgnum %>"> +<INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $svcpart %>"> +<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#cccccc"> +<TR> + <TD ALIGN="right">Username</TD> + <TD><INPUT TYPE="text" NAME="username" VALUE="<%= $username %>"></TD> +</TR> +<TR> + <TD ALIGN="right">Password</TD> + <TD><INPUT TYPE="password" NAME="_password" VALUE="<%= $_password %>"></TD> +</TR> +<TR> + <TD ALIGN="right">Re-enter Password</TD> + <TD><INPUT TYPE="password" NAME="_password2" VALUE="<%= $_password2 %>"></TD> +</TR> +<%= + if ( $security_phrase ) { + $OUT .= <<ENDOUT; +<TR> + <TD ALIGN="right">Security Phrase</TD> + <TD><INPUT TYPE="text" NAME="sec_phrase" VALUE="$sec_phrase"> + </TD> +</TR> +ENDOUT + } else { + $OUT .= '<INPUT TYPE="hidden" NAME="sec_phrase" VALUE="">'; + } +%> +<%= + if ( @svc_acct_pop ) { + $OUT .= '<TR><TD ALIGN="right">Access number</TD><TD>'. + popselector( 'popnum' => $popnum, + 'pops' => \@svc_acct_pop, + 'init_popstate' => $init_popstate, + 'popac' => $popac, + 'acstate' => $acstate, + ). + '</TD></TR>'; + } else { + $OUT .= popselector(popnum=>$popnum, pops=>\@svc_acct_pop); + } +%> +</TABLE> +<INPUT TYPE="submit" VALUE="Setup"> +</FORM> + +</TD></TR></TABLE> +<HR> +<FONT SIZE="-2">powered by <a href="http://www.sisd.com/freeside">freeside</a></FONT> +</BODY></HTML> + diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index 6d6716ddc..d8e044a96 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -6,8 +6,11 @@ use subs qw(do_template); use CGI; use CGI::Carp qw(fatalsToBrowser); use Text::Template; -use FS::SelfService qw( login customer_info invoice payment_info - process_payment ); +use FS::SelfService qw( login customer_info invoice + payment_info process_payment + list_pkgs + part_svc_info provision_acct unprovision_svc + ); $template_dir = '.'; @@ -54,8 +57,9 @@ if ( $cgi->param('session') eq 'login' ) { $session_id = $cgi->param('session'); +#order|pw_list XXX ??? $cgi->param('action') =~ - /^(myaccount|view_invoice|make_payment|payment_results)$/ + /^(myaccount|view_invoice|make_payment|payment_results|logout|change_bill|change_ship|provision|provision_svc|process_svc_acct|delete_svc)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -167,6 +171,63 @@ sub payment_results { } +sub logout { + FS::SelfService::logout( 'session_id' => $session_id ); +} + +sub provision { + list_pkgs( 'session_id' => $session_id ); +} + +sub provision_svc { + + my $result = part_svc_info( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } qw( pkgnum svcpart ), + ); + die $result->{'error'} if exists $result->{'error'} && $result->{'error'}; + + $result->{'svcdb'} =~ /^svc_(.*)$/ + #or return { 'error' => 'Unknown svcdb '. $result->{'svcdb'} }; + or die 'Unknown svcdb '. $result->{'svcdb'}; + $action .= "_$1"; + + $result; +} + +sub process_svc_acct { + + my $result = provision_acct ( + 'session_id' => $session_id, + map { $_ => $cgi->param($_) } qw( + pkgnum svcpart username _password _password2 sec_phrase popnum ) + ); + + if ( exists $result->{'error'} && $result->{'error'} ) { + warn "$result $result->{'error'}"; + $action = 'provision_svc_acct'; + return { + $cgi->Vars, + %{ part_svc_info( 'session_id' => $session_id, + map { $_ => $cgi->param($_) } qw( pkgnum svcpart ) + ) + }, + 'error' => $result->{'error'}, + }; + } else { + warn "$result $result->{'error'}"; + return $result; + } + +} + +sub delete_svc { + unprovision_svc( + 'session_id' => $session_id, + 'svcnum' => $cgi->param('svcnum'), + ); +} + #-- sub do_template { @@ -175,6 +236,7 @@ sub do_template { $cgi->delete_all(); $fill_in->{'selfurl'} = $cgi->self_url; + $fill_in->{'cgi'} = \$cgi; my $template = new Text::Template( TYPE => 'FILE', SOURCE => "$template_dir/$name.html", @@ -183,6 +245,28 @@ sub do_template { or die $Text::Template::ERROR; print $cgi->header( '-expires' => 'now' ), - $template->fill_in( HASH => $fill_in ); + $template->fill_in( PACKAGE => 'FS::SelfService::_selfservicecgi', + HASH => $fill_in + ); +} + +#*FS::SelfService::_selfservicecgi::include = \&Text::Template::fill_in_file; + +package FS::SelfService::_selfservicecgi; + +#use FS::SelfService qw(regionselector expselect popselector); +use FS::SelfService qw(popselector); + +sub include { + my $name = shift; + my $template = new Text::Template( TYPE => 'FILE', + SOURCE => "$main::template_dir/$name.html", + DELIMITERS => [ '<%=', '%>' ], + UNTAINT => 1, + ) + or die $Text::Template::ERROR; + + $template->fill_in(); + } diff --git a/fs_selfservice/FS-SelfService/cgi/view_invoice.html b/fs_selfservice/FS-SelfService/cgi/view_invoice.html index d2b012b5d..46f731890 100644 --- a/fs_selfservice/FS-SelfService/cgi/view_invoice.html +++ b/fs_selfservice/FS-SelfService/cgi/view_invoice.html @@ -1,12 +1,9 @@ <HTML><HEAD><TITLE>MyAccount</TITLE></HEAD> <BODY BGCOLOR="#eeeeee"><FONT SIZE=5>MyAccount</FONT><BR><BR> <%= $url = "$selfurl?session=$session_id;action="; ''; %> -<TABLE BORDER=0 CELLPADDING=4><TR><TD VALIGN="top" HEIGHT=384 BGCOLOR="#dddddd"> -<A HREF="<%= $url %>myaccount">MyAccount</A><BR> -<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> --> -</TD><TD VALIGN="top"> - -<A HREF="<%= $url %>myaccount"><-- back to MyAccount</A><BR><BR> +<TABLE BORDER=0 CELLPADDING=4><TR> +<%= include('myaccount_menu') %> +<TD VALIGN="top"> <FONT SIZE="-1"><PRE> <%= $invoice_text %> diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 4497713c9..4ed30b813 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -897,28 +897,14 @@ sub get_packages { $pkg{expire} = $cust_pkg->getfield('expire'); $pkg{cancel} = $cust_pkg->getfield('cancel'); - my %svcparts = (); - - foreach my $pkg_svc ( - qsearch('pkg_svc', { 'pkgpart' => $part_pkg->pkgpart }) - ) { - - next if ($pkg_svc->quantity == 0); - - my $part_svc = qsearchs('part_svc', { 'svcpart' => $pkg_svc->svcpart }); - - my $svcpart = {}; - $svcpart->{svcpart} = $part_svc->svcpart; - $svcpart->{svc} = $part_svc->svc; - $svcpart->{svcdb} = $part_svc->svcdb; - $svcpart->{quantity} = $pkg_svc->quantity; - $svcpart->{count} = 0; - - $svcpart->{services} = []; - - $svcparts{$svcpart->{svcpart}} = $svcpart; - - } + my %svcparts = map { + $_->svcpart => { + $_->part_svc->hash, + 'quantity' => $_->quantity, + 'count' => $cust_pkg->num_cust_svc($_->svcpart), + #'services' => [], + }; + } $part_pkg->pkg_svc; foreach my $cust_svc ( $cust_pkg->cust_svc ) { #warn "svcnum ". $cust_svc->svcnum. " / svcpart ". $cust_svc->svcpart. "\n"; @@ -930,18 +916,14 @@ sub get_packages { #false laziness with above, to catch extraneous services. whole #damn thing should be OO... my $svcpart = ( $svcparts{$cust_svc->svcpart} ||= { - 'svcpart' => $cust_svc->svcpart, - 'svc' => $cust_svc->part_svc->svc, - 'svcdb' => $cust_svc->part_svc->svcdb, + $cust_svc->part_svc->hash, 'quantity' => 0, - 'count' => 0, - 'services' => [], + 'count' => $cust_pkg->num_cust_svc($cust_svc->svcpart), + #'services' => [], } ); push @{$svcpart->{services}}, $svc; - $svcpart->{count}++; - } $pkg{svcparts} = [ values %svcparts ]; |