summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan <ivan>2004-06-10 12:31:32 +0000
committerivan <ivan>2004-06-10 12:31:32 +0000
commit3913f6d159b5b8110061690b7c97642c27abf7eb (patch)
treea5bc48080901dfe6c19c864c2c2f374990a2cfdd
parente0c62c388f74e543328f3691e8a8a1edb451a804 (diff)
agent interface
-rw-r--r--FS/FS/CGI.pm33
-rw-r--r--FS/FS/ClientAPI/Agent.pm113
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm79
-rw-r--r--FS/FS/ClientAPI/Signup.pm64
-rw-r--r--FS/FS/agent.pm104
-rw-r--r--FS/FS/cust_main.pm130
-rw-r--r--fs_selfservice/FS-SelfService/SelfService.pm446
-rw-r--r--fs_selfservice/FS-SelfService/cgi/agent.cgi256
-rw-r--r--fs_selfservice/FS-SelfService/cgi/agent_login.html22
-rw-r--r--fs_selfservice/FS-SelfService/cgi/agent_main.html40
-rw-r--r--fs_selfservice/FS-SelfService/cgi/cvv2.html25
-rw-r--r--fs_selfservice/FS-SelfService/cgi/cvv2.pngbin0 -> 3854 bytes
-rw-r--r--fs_selfservice/FS-SelfService/cgi/cvv2_amex.pngbin0 -> 4573 bytes
-rw-r--r--fs_selfservice/FS-SelfService/cgi/list_customers.html41
-rwxr-xr-xfs_selfservice/FS-SelfService/cgi/signup.html233
-rw-r--r--fs_selfservice/FS-SelfService/cgi/view_customer.html84
-rw-r--r--fs_signup/FS-SignupClient/SignupClient.pm52
-rwxr-xr-xfs_signup/FS-SignupClient/cgi/signup.cgi267
-rwxr-xr-xhttemplate/browse/agent.cgi28
-rwxr-xr-xhttemplate/search/cust_main.cgi111
20 files changed, 1720 insertions, 408 deletions
diff --git a/FS/FS/CGI.pm b/FS/FS/CGI.pm
index a3286299b..1ddc62c7a 100644
--- a/FS/FS/CGI.pm
+++ b/FS/FS/CGI.pm
@@ -294,6 +294,8 @@ sub small_custview {
or die "unknown custnum $arg";
my $html = 'Customer #<B>'. $cust_main->custnum. '</B>'.
+ ' - <B><FONT COLOR="'. $cust_main->statuscolor. '">'.
+ ucfirst($cust_main->status). '</FONT></B>'.
ntable('#e8e8e8'). '<TR><TD>'. ntable("#cccccc",2).
'<TR><TD ALIGN="right" VALIGN="top">Billing<BR>Address</TD><TD BGCOLOR="#ffffff">'.
$cust_main->getfield('last'). ', '. $cust_main->first. '<BR>';
@@ -305,6 +307,20 @@ sub small_custview {
$html .= $cust_main->country. '<BR>'
if $cust_main->country && $cust_main->country ne $countrydefault;
+ $html .= '</TD></TR><TR><TD></TD><TD BGCOLOR="#ffffff">';
+ if ( $cust_main->daytime && $cust_main->night ) {
+ use FS::Msgcat;
+ $html .= ( FS::Msgcat::_gettext('daytime') || 'Day' ).
+ ' '. $cust_main->daytime.
+ '<BR>'. ( FS::Msgcat::_gettext('night') || 'Night' ).
+ ' '. $cust_main->night;
+ } elsif ( $cust_main->daytime || $cust_main->night ) {
+ $html .= $cust_main->daytime || $cust_main->night;
+ }
+ if ( $cust_main->fax ) {
+ $html .= '<BR>Fax '. $cust_main->fax;
+ }
+
$html .= '</TD></TR></TABLE></TD>';
if ( defined $cust_main->dbdef_table->column('ship_last') ) {
@@ -327,6 +343,23 @@ sub small_custview {
if $cust_main->get("${pre}country")
&& $cust_main->get("${pre}country") ne $countrydefault;
+ $html .= '</TD></TR><TR><TD></TD><TD BGCOLOR="#ffffff">';
+
+ if ( $cust_main->get("${pre}daytime") && $cust_main->get("${pre}night") ) {
+ use FS::Msgcat;
+ $html .= ( FS::Msgcat::_gettext('daytime') || 'Day' ).
+ ' '. $cust_main->get("${pre}daytime").
+ '<BR>'. ( FS::Msgcat::_gettext('night') || 'Night' ).
+ ' '. $cust_main->get("${pre}night");
+ } elsif ( $cust_main->get("${pre}daytime")
+ || $cust_main->get("${pre}night") ) {
+ $html .= $cust_main->get("${pre}daytime")
+ || $cust_main->get("${pre}night");
+ }
+ if ( $cust_main->get("${pre}fax") ) {
+ $html .= '<BR>Fax '. $cust_main->get("${pre}fax");
+ }
+
$html .= '</TD></TR></TABLE></TD>';
}
diff --git a/FS/FS/ClientAPI/Agent.pm b/FS/FS/ClientAPI/Agent.pm
new file mode 100644
index 000000000..212faaa6b
--- /dev/null
+++ b/FS/FS/ClientAPI/Agent.pm
@@ -0,0 +1,113 @@
+package FS::ClientAPI::Agent;
+
+#some false laziness w/MyAccount
+
+use strict;
+use vars qw($cache);
+use Digest::MD5 qw(md5_hex);
+use Cache::SharedMemoryCache; #store in db?
+use FS::Record qw(qsearchs); # qsearch);
+use FS::agent;
+
+use FS::ClientAPI;
+FS::ClientAPI->register_handlers(
+ 'Agent/agent_login' => \&agent_login,
+ 'Agent/agent_info' => \&agent_info,
+ 'Agent/agent_list_customers' => \&agent_list_customers,
+);
+
+#store in db?
+my $cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::Agent',
+} );
+
+sub agent_login {
+ my $p = shift;
+
+ #don't allow a blank login to first unconfigured agent with no user/pass
+ return { error => 'Must specify your reseller username and password.' }
+ unless length($p->{'username'}) && length($p->{'password'});
+
+ my $agent = qsearchs( 'agent', {
+ 'username' => $p->{'username'},
+ '_password' => $p->{'password'},
+ } );
+
+ unless ( $agent ) { return { error => 'Incorrect password.' } }
+
+ my $session = {
+ 'agentnum' => $agent->agentnum,
+ 'agent' => $agent->agent,
+ };
+
+ my $session_id;
+ do {
+ $session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
+ } until ( ! defined $cache->get($session_id) ); #just in case
+
+ $cache->set( $session_id, $session, '1 hour' );
+
+ { 'error' => '',
+ 'session_id' => $session_id,
+ };
+}
+
+sub agent_info {
+ my $p = shift;
+
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ #my %return;
+
+ my $agentnum = $session->{'agentnum'};
+
+ my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
+ or return { 'error' => "unknown agentnum $agentnum" };
+
+ { 'error' => '',
+ 'agentnum' => $agentnum,
+ 'agent' => $agent->agent,
+ 'num_prospect' => $agent->num_prospect_cust_main,
+ 'num_active' => $agent->num_active_cust_main,
+ 'num_susp' => $agent->num_susp_cust_main,
+ 'num_cancel' => $agent->num_cancel_cust_main,
+ #%return,
+ };
+
+}
+
+sub agent_list_customers {
+ my $p = shift;
+
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ #my %return;
+
+ my $agentnum = $session->{'agentnum'};
+
+ my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
+ or return { 'error' => "unknown agentnum $agentnum" };
+
+ my @cust_main = ();
+
+ warn $p->{'susp'};
+
+ push @cust_main,
+ map $agent->$_(), map $_.'_cust_main',
+ grep $p->{$_}, qw( prospect active susp cancel );
+
+ { customers => [ map {
+ my $cust_main = $_;
+ my $hashref = $cust_main->hashref;
+ $hashref->{$_} = $cust_main->$_()
+ foreach qw(name status statuscolor);
+ delete $hashref->{$_} foreach qw( payinfo paycvv );
+ $hashref;
+ } @cust_main
+ ],
+ }
+
+}
+
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index 77c1fc889..271d0c2cc 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -25,6 +25,7 @@ FS::ClientAPI->register_handlers(
'MyAccount/customer_info' => \&customer_info,
'MyAccount/edit_info' => \&edit_info,
'MyAccount/invoice' => \&invoice,
+ 'MyAccount/list_invoices' => \&list_invoices,
'MyAccount/cancel' => \&cancel,
'MyAccount/payment_info' => \&payment_info,
'MyAccount/process_payment' => \&process_payment,
@@ -86,16 +87,31 @@ sub login {
sub customer_info {
my $p = shift;
- my $session = $cache->get($p->{'session_id'})
- or return { 'error' => "Can't resume session" }; #better error message
-
- my %return;
- my $custnum = $session->{'custnum'};
+ my($session, $custnum, $context);
+ if ( $p->{'session_id'} ) {
+ $context = 'customer';
+ $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+ $custnum = $session->{'custnum'};
+ } elsif ( $p->{'agent_session_id'} ) {
+ $context = 'agent';
+ my $agent_cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::Agent',
+ } );
+ $session = $agent_cache->get($p->{'agent_session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+ $custnum = $p->{'custnum'};
+ } else {
+ return { 'error' => "Can't resume session" }; #better error message
+ }
+ my %return;
if ( $custnum ) { #customer record
- my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ my $search = { 'custnum' => $custnum };
+ $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
+ my $cust_main = qsearchs('cust_main', $search )
or return { 'error' => "unknown custnum $custnum" };
$return{balance} = $cust_main->balance;
@@ -357,6 +373,27 @@ sub invoice {
}
+sub list_invoices {
+ 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 @cust_bill = $cust_main->cust_bill;
+
+ return { 'error' => '',
+ 'invoices' => [ map { { 'invnum' => $_->invnum,
+ '_date' => $_->_date,
+ }
+ } @cust_bill
+ ]
+ };
+}
+
sub cancel {
my $p = shift;
my $session = $cache->get($p->{'session_id'})
@@ -391,12 +428,30 @@ sub list_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($session, $custnum, $context);
+
+ if ( $p->{'session_id'} ) {
+ $context = 'customer';
+ $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+ $custnum = $session->{'custnum'};
+ } elsif ( $p->{'agent_session_id'} ) {
+ $context = 'agent';
+ my $agent_cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::Agent',
+ } );
+ $session = $agent_cache->get($p->{'agent_session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+ $custnum = $p->{'custnum'};
+ } else {
+ return { 'error' => "Can't resume session" }; #better error message
+ }
- my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ my $search = { 'custnum' => $custnum };
+ $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent';
+
+ my $cust_main = qsearchs('cust_main', $search )
or return { 'error' => "unknown custnum $custnum" };
#false laziness w/ClientAPI/Signup.pm
@@ -503,13 +558,13 @@ sub cancel_pkg {
my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
or return { 'error' => "unknown custnum $custnum" };
- my $pkgnum = $session->{'pkgnum'};
+ my $pkgnum = $p->{'pkgnum'};
my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum,
'pkgnum' => $pkgnum, } )
or return { 'error' => "unknown pkgnum $pkgnum" };
- my $error = $cust_main->cancel( 'quiet'=>1 );
+ my $error = $cust_pkg->cancel( 'quiet'=>1 );
return { 'error' => $error };
}
diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm
index 4655b0984..2e2b80fcb 100644
--- a/FS/FS/ClientAPI/Signup.pm
+++ b/FS/FS/ClientAPI/Signup.pm
@@ -22,7 +22,7 @@ FS::ClientAPI->register_handlers(
);
sub signup_info {
- #my $packet = shift;
+ my $packet = shift;
my $conf = new FS::Conf;
@@ -87,24 +87,35 @@ sub signup_info {
};
- if (
- $conf->config('signup_server-default_agentnum')
- && !exists $signup_info->{'part_pkg'} #cache for performance
- ) {
- my $agentnum = $conf->config('signup_server-default_agentnum');
- my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
- or die "fatal: signup_server-default_agentnum $agentnum not found\n";
- my $pkgpart_href = $agent->pkgpart_hashref;
-
- $signup_info->{'part_pkg'} = [
- #map { $_->hashref }
- map { { 'payby' => [ $_->payby ], %{$_->hashref} } }
- grep { $_->svcpart('svc_acct') && $pkgpart_href->{ $_->pkgpart } }
- qsearch( 'part_pkg', { 'disabled' => '' } )
- ];
+ my $agentnum = $conf->config('signup_server-default_agentnum');
+
+ my $session = '';
+ if ( exists $packet->{'session_id'} ) {
+ my $cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::Agent',
+ } );
+ $session = $cache->get($packet->{'session_id'});
+ if ( $session ) {
+ $agentnum = $session->{'agentnum'};
+ } else {
+ return { 'error' => "Can't resume session" }; #better error message
+ }
}
- $signup_info;
+ if ( $agentnum ) {
+ $signup_info->{'part_pkg'} = $signup_info->{'agentnum2part_pkg'}{$agentnum};
+ } else {
+ delete $signup_info->{'part_pkg'};
+ }
+
+ if ( $session ) {
+ my $agent_signup_info = { %$signup_info };
+ delete $agent_signup_info->{agentnum2part_pkg};
+ $agent_signup_info->{'agent'} = $session->{'agent'};
+ $agent_signup_info;
+ } else {
+ $signup_info;
+ }
}
@@ -122,12 +133,27 @@ sub new_customer {
return { 'error' => gettext('no_access_number_selected') }
unless $packet->{'popnum'} || !scalar(qsearch('svc_acct_pop',{} ));
+ my $agentnum;
+ if ( exists $packet->{'session_id'} ) {
+ my $cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::Agent',
+ } );
+ my $session = $cache->get($packet->{'session_id'});
+ if ( $session ) {
+ $agentnum = $session->{'agentnum'};
+ } else {
+ return { 'error' => "Can't resume session" }; #better error message
+ }
+ } else {
+ $agentnum = $packet->{agentnum}
+ || $conf->config('signup_server-default_agentnum');
+ }
+
#shares some stuff with htdocs/edit/process/cust_main.cgi... take any
# common that are still here and library them.
my $cust_main = new FS::cust_main ( {
#'custnum' => '',
- 'agentnum' => $packet->{agentnum}
- || $conf->config('signup_server-default_agentnum'),
+ 'agentnum' => $agentnum,
'refnum' => $packet->{refnum}
|| $conf->config('signup_server-default_refnum'),
diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm
index 2f70d654d..7c69dfbf2 100644
--- a/FS/FS/agent.pm
+++ b/FS/FS/agent.pm
@@ -2,7 +2,7 @@ package FS::agent;
use strict;
use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
+use FS::Record qw( dbh qsearch qsearchs );
use FS::cust_main;
use FS::agent_type;
@@ -164,11 +164,107 @@ sub pkgpart_hashref {
$self->agent_type->pkgpart_hashref;
}
-=back
+=item num_prospect_cust_main
+
+Returns the number of prospects (customers with no packages ever ordered) for
+this agent.
+
+=cut
+
+sub num_prospect_cust_main {
+ shift->num_sql(FS::cust_main->prospect_sql);
+}
+
+sub num_sql {
+ my( $self, $sql ) = @_;
+ my $sth = dbh->prepare(
+ "SELECT COUNT(*) FROM cust_main WHERE agentnum = ? AND $sql"
+ ) or die dbh->errstr;
+ $sth->execute($self->agentnum) or die $sth->errstr;
+ $sth->fetchrow_arrayref->[0];
+}
+
+=item prospect_cust_main
+
+Returns the prospects (customers with no packages ever ordered) for this agent,
+as cust_main objects.
+
+=cut
+
+sub prospect_cust_main {
+ shift->cust_main_sql(FS::cust_main->prospect_sql);
+}
+
+sub cust_main_sql {
+ my( $self, $sql ) = @_;
+ qsearch( 'cust_main',
+ { 'agentnum' => $self->agentnum },
+ '',
+ " AND $sql"
+ );
+}
+
+=item num_active_cust_main
+
+Returns the number of active customers for this agent.
+
+=cut
+
+sub num_active_cust_main {
+ shift->num_sql(FS::cust_main->active_sql);
+}
+
+=item active_cust_main
+
+Returns the active customers for this agent, as cust_main objects.
+
+=cut
-=head1 VERSION
+sub active_cust_main {
+ shift->cust_main_sql(FS::cust_main->active_sql);
+}
+
+=item num_susp_cust_main
+
+Returns the number of suspended customers for this agent.
+
+=cut
+
+sub num_susp_cust_main {
+ shift->num_sql(FS::cust_main->susp_sql);
+}
+
+=item susp_cust_main
+
+Returns the suspended customers for this agent, as cust_main objects.
+
+=cut
+
+sub susp_cust_main {
+ shift->cust_main_sql(FS::cust_main->susp_sql);
+}
-$Id: agent.pm,v 1.6 2003-09-30 15:01:46 ivan Exp $
+=item num_cancel_cust_main
+
+Returns the number of cancelled customer for this agent.
+
+=cut
+
+sub num_cancel_cust_main {
+ shift->num_sql(FS::cust_main->cancel_sql);
+}
+
+=item cancel_cust_main
+
+Returns the cancelled customers for this agent, as cust_main objects.
+
+=cut
+
+sub cancel_cust_main {
+ shift->cust_main_sql(FS::cust_main->cancel_sql);
+}
+
+=back
=head1 BUGS
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index fbd461841..07f0a34e5 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -2538,6 +2538,136 @@ sub select_for_update {
qsearch('cust_main', { 'custnum' => $self->custnum }, '*', 'FOR UPDATE' );
}
+=item name
+
+Returns a name string for this customer, either "Company (Last, First)" or
+"Last, First".
+
+=cut
+
+sub name {
+ my $self = shift;
+ my $name = $self->get('last'). ', '. $self->first;
+ $name = $self->company. " ($name)" if $self->company;
+ $name;
+}
+
+=item status
+
+Returns a status string for this customer, currently:
+
+=over 4
+
+=item prospect - No packages have ever been ordered
+
+=item active - One or more recurring packages is active
+
+=item suspended - All non-cancelled recurring packages are suspended
+
+=item cancelled - All recurring packages are cancelled
+
+=back
+
+=cut
+
+sub status {
+ my $self = shift;
+ for my $status (qw( prospect active suspended cancelled )) {
+ my $method = $status.'_sql';
+ my $numnum = ( my $sql = $self->$method() ) =~ s/cust_main\.custnum/?/g;
+ my $sth = dbh->prepare("SELECT $sql") or die dbh->errstr;
+ $sth->execute( ($self->custnum) x $numnum ) or die $sth->errstr;
+ return $status if $sth->fetchrow_arrayref->[0];
+ }
+}
+
+=item statuscolor
+
+Returns a hex triplet color string for this customer's status.
+
+=cut
+
+my %statuscolor = (
+ 'prospect' => '000000',
+ 'active' => '00CC00',
+ 'suspended' => 'FF9900',
+ 'cancelled' => 'FF0000',
+);
+sub statuscolor {
+ my $self = shift;
+ $statuscolor{$self->status};
+}
+
+=back
+
+=head1 CLASS METHODS
+
+=over 4
+
+=item prospect_sql
+
+Returns an SQL expression identifying prospective cust_main records (customers
+with no packages ever ordered)
+
+=cut
+
+sub prospect_sql { "
+ 0 = ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ )
+"; }
+
+=item active_sql
+
+Returns an SQL expression identifying active cust_main records.
+
+=cut
+
+sub active_sql { "
+ 0 < ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
+ )
+"; }
+
+=item susp_sql
+=item suspended_sql
+
+Returns an SQL expression identifying suspended cust_main records.
+
+=cut
+
+sub suspended_sql { susp_sql(@_); }
+sub susp_sql { "
+ 0 < ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ )
+ AND 0 = ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
+ )
+"; }
+
+=item cancel_sql
+=item cancelled_sql
+
+Returns an SQL expression identifying cancelled cust_main records.
+
+=cut
+
+sub cancelled_sql { cancel_sql(@_); }
+sub cancel_sql { "
+ 0 < ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ )
+ AND 0 = ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ )
+"; }
+
=back
=head1 SUBROUTINES
diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm
index 920415e30..2cda9fe2d 100644
--- a/fs_selfservice/FS-SelfService/SelfService.pm
+++ b/fs_selfservice/FS-SelfService/SelfService.pm
@@ -18,24 +18,28 @@ $socket .= '.'.$tag if defined $tag && length($tag);
#maybe should ask ClientAPI for this list
%autoload = (
- 'passwd' => 'passwd/passwd',
- 'chfn' => 'passwd/passwd',
- 'chsh' => 'passwd/passwd',
- 'login' => 'MyAccount/login',
- 'customer_info' => 'MyAccount/customer_info',
- 'edit_info' => 'MyAccount/edit_info',
- 'invoice' => 'MyAccount/invoice',
- 'cancel' => 'MyAccount/cancel',
- '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',
- 'signup_info' => 'Signup/signup_info',
- 'new_customer' => 'Signup/new_customer',
+ 'passwd' => 'passwd/passwd',
+ 'chfn' => 'passwd/passwd',
+ 'chsh' => 'passwd/passwd',
+ 'login' => 'MyAccount/login',
+ 'customer_info' => 'MyAccount/customer_info',
+ 'edit_info' => 'MyAccount/edit_info',
+ 'invoice' => 'MyAccount/invoice',
+ 'list_invoices' => 'MyAccount/list_invoices',
+ 'cancel' => 'MyAccount/cancel',
+ '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',
+ 'signup_info' => 'Signup/signup_info',
+ 'new_customer' => 'Signup/new_customer',
+ 'agent_login' => 'Agent/agent_login',
+ 'agent_info' => 'Agent/agent_info',
+ 'agent_list_customers' => 'Agent/agent_list_customers',
);
-@EXPORT_OK = keys %autoload;
+@EXPORT_OK = ( keys(%autoload), qw( regionselector expselect popselector ) );
$ENV{'PATH'} ='/usr/bin:/usr/ucb:/bin';
$ENV{'SHELL'} = '/bin/sh';
@@ -286,6 +290,37 @@ Invoice text
=back
+=item list_invoices HASHREF
+
+Returns a list of all customer invoices. Takes a hash references with a single
+key, session_id.
+
+Returns a hash reference with the following keys:
+
+=over 4
+
+=item error
+
+Empty on success, or an error message on errors
+
+=item invoices
+
+Reference to array of hash references with the following keys:
+
+=over 4
+
+=item invnum
+
+Invoice ID
+
+=item _date
+
+Invoice date, in UNIX epoch time
+
+=back
+
+=back
+
=item cancel HASHREF
Cancels this customer.
@@ -492,7 +527,15 @@ error message on errors.
=over 4
-=item signup_info
+=item signup_info HASHREF
+
+Takes a hash reference as parameter with the following keys:
+
+=over 4
+
+=item session_id - Optional agent/reseller interface session
+
+=back
Returns a hash reference containing information that may be useful in
displaying a signup page. The hash reference contains the following keys:
@@ -505,7 +548,9 @@ County/state/country data - array reference of hash references, each of which ha
=item part_pkg
-Available packages - array reference of hash references, each of which has the fields of a part_pkg record (see L<FS::part_pkg>). Each hash reference also has an additional 'payby' field containing an array reference of acceptable payment types specific to this package (see below and L<FS::part_pkg/payby>). Note these are not FS::part_pkg objects, but hash references of columns and values. Requires the 'signup_server-default_agentnum' configuration value to be set.
+Available packages - array reference of hash references, each of which has the fields of a part_pkg record (see L<FS::part_pkg>). Each hash reference also has an additional 'payby' field containing an array reference of acceptable payment types specific to this package (see below and L<FS::part_pkg/payby>). Note these are not FS::part_pkg objects, but hash references of columns and values. Requires the 'signup_server-default_agentnum' configuration value to be set, or
+an agentnum specified explicitly via reseller interface session_id in the
+options.
=item agent
@@ -634,6 +679,369 @@ Returns a hash reference with the following keys:
=back
+=item regionselector HASHREF | LIST
+
+Takes as input a hashref or list of key/value pairs with the following keys:
+
+=over 4
+
+=item selected_county
+
+=item selected_state
+
+=item selected_country
+
+=item prefix - Specify a unique prefix string if you intend to use the HTML output multiple time son one page.
+
+=item onchange - Specify a javascript subroutine to call on changes
+
+=item default_state
+
+=item default_country
+
+=item locales - An arrayref of hash references specifying regions. Normally you can just pass the value of the I<cust_main_county> field returned by B<signup_info>.
+
+=back
+
+Returns a list consisting of three HTML fragments for county selection,
+state selection and country selection, respectively.
+
+=cut
+
+#false laziness w/FS::cust_main_county (this is currently the "newest" version)
+sub regionselector {
+ my $param;
+ if ( ref($_[0]) ) {
+ $param = shift;
+ } else {
+ $param = { @_ };
+ }
+ $param->{'selected_country'} ||= $param->{'default_country'};
+ $param->{'selected_state'} ||= $param->{'default_state'};
+
+ my $prefix = exists($param->{'prefix'}) ? $param->{'prefix'} : '';
+
+ my $countyflag = 0;
+
+ my %cust_main_county;
+
+# unless ( @cust_main_county ) { #cache
+ #@cust_main_county = qsearch('cust_main_county', {} );
+ #foreach my $c ( @cust_main_county ) {
+ foreach my $c ( @{ $param->{'locales'} } ) {
+ #$countyflag=1 if $c->county;
+ $countyflag=1 if $c->{county};
+ #push @{$cust_main_county{$c->country}{$c->state}}, $c->county;
+ #$cust_main_county{$c->country}{$c->state}{$c->county} = 1;
+ $cust_main_county{$c->{country}}{$c->{state}}{$c->{county}} = 1;
+ }
+# }
+ $countyflag=1 if $param->{selected_county};
+
+ my $script_html = <<END;
+ <SCRIPT>
+ function opt(what,value,text) {
+ var optionName = new Option(text, value, false, false);
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+ function ${prefix}country_changed(what) {
+ country = what.options[what.selectedIndex].text;
+ for ( var i = what.form.${prefix}state.length; i >= 0; i-- )
+ what.form.${prefix}state.options[i] = null;
+END
+ #what.form.${prefix}state.options[0] = new Option('', '', false, true);
+
+ foreach my $country ( sort keys %cust_main_county ) {
+ $script_html .= "\nif ( country == \"$country\" ) {\n";
+ foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
+ my $text = $state || '(n/a)';
+ $script_html .= qq!opt(what.form.${prefix}state, "$state", "$text");\n!;
+ }
+ $script_html .= "}\n";
+ }
+
+ $script_html .= <<END;
+ }
+ function ${prefix}state_changed(what) {
+END
+
+ if ( $countyflag ) {
+ $script_html .= <<END;
+ state = what.options[what.selectedIndex].text;
+ country = what.form.${prefix}country.options[what.form.${prefix}country.selectedIndex].text;
+ for ( var i = what.form.${prefix}county.length; i >= 0; i-- )
+ what.form.${prefix}county.options[i] = null;
+END
+
+ foreach my $country ( sort keys %cust_main_county ) {
+ $script_html .= "\nif ( country == \"$country\" ) {\n";
+ foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
+ $script_html .= "\nif ( state == \"$state\" ) {\n";
+ #foreach my $county ( sort @{$cust_main_county{$country}{$state}} ) {
+ foreach my $county ( sort keys %{$cust_main_county{$country}{$state}} ) {
+ my $text = $county || '(n/a)';
+ $script_html .=
+ qq!opt(what.form.${prefix}county, "$county", "$text");\n!;
+ }
+ $script_html .= "}\n";
+ }
+ $script_html .= "}\n";
+ }
+ }
+
+ $script_html .= <<END;
+ }
+ </SCRIPT>
+END
+
+ my $county_html = $script_html;
+ if ( $countyflag ) {
+ $county_html .= qq!<SELECT NAME="${prefix}county" onChange="$param->{'onchange'}">!;
+ $county_html .= '</SELECT>';
+ } else {
+ $county_html .=
+ qq!<INPUT TYPE="hidden" NAME="${prefix}county" VALUE="$param->{'selected_county'}">!;
+ }
+
+ my $state_html = qq!<SELECT NAME="${prefix}state" !.
+ qq!onChange="${prefix}state_changed(this); $param->{'onchange'}">!;
+ foreach my $state ( sort keys %{ $cust_main_county{$param->{'selected_country'}} } ) {
+ my $text = $state || '(n/a)';
+ my $selected = $state eq $param->{'selected_state'} ? 'SELECTED' : '';
+ $state_html .= "\n<OPTION $selected VALUE=$state>$text</OPTION>"
+ }
+ $state_html .= '</SELECT>';
+
+ $state_html .= '</SELECT>';
+
+ my $country_html = qq!<SELECT NAME="${prefix}country" !.
+ qq!onChange="${prefix}country_changed(this); $param->{'onchange'}">!;
+ my $countrydefault = $param->{default_country} || 'US';
+ foreach my $country (
+ sort { ($b eq $countrydefault) <=> ($a eq $countrydefault) or $a cmp $b }
+ keys %cust_main_county
+ ) {
+ my $selected = $country eq $param->{'selected_country'} ? ' SELECTED' : '';
+ $country_html .= "\n<OPTION$selected>$country</OPTION>"
+ }
+ $country_html .= '</SELECT>';
+
+ ($county_html, $state_html, $country_html);
+
+}
+
+#=item expselect HASHREF | LIST
+#
+#Takes as input a hashref or list of key/value pairs with the following keys:
+#
+#=over 4
+#
+#=item prefix - Specify a unique prefix string if you intend to use the HTML output multiple time son one page.
+#
+#=item date - current date, in yyyy-mm-dd or m-d-yyyy format
+#
+#=back
+
+=item expselect PREFIX [ DATE ]
+
+Takes as input a unique prefix string and the current expiration date, in
+yyyy-mm-dd or m-d-yyyy format
+
+Returns an HTML fragments for expiration date selection.
+
+=cut
+
+sub expselect {
+ #my $param;
+ #if ( ref($_[0]) ) {
+ # $param = shift;
+ #} else {
+ # $param = { @_ };
+ #my $prefix = $param->{'prefix'};
+ #my $prefix = exists($param->{'prefix'}) ? $param->{'prefix'} : '';
+ #my $date = exists($param->{'date'}) ? $param->{'date'} : '';
+ my $prefix = shift;
+ my $date = scalar(@_) ? shift : '';
+
+ my( $m, $y ) = ( 0, 0 );
+ if ( $date =~ /^(\d{4})-(\d{2})-\d{2}$/ ) { #PostgreSQL date format
+ ( $m, $y ) = ( $2, $1 );
+ } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
+ ( $m, $y ) = ( $1, $3 );
+ }
+ my $return = qq!<SELECT NAME="$prefix!. qq!_month" SIZE="1">!;
+ for ( 1 .. 12 ) {
+ $return .= "<OPTION";
+ $return .= " SELECTED" if $_ == $m;
+ $return .= ">$_";
+ }
+ $return .= qq!</SELECT>/<SELECT NAME="$prefix!. qq!_year" SIZE="1">!;
+ my @t = localtime;
+ my $thisYear = $t[5] + 1900;
+ for ( ($thisYear > $y && $y > 0 ? $y : $thisYear) .. 2037 ) {
+ $return .= "<OPTION";
+ $return .= " SELECTED" if $_ == $y;
+ $return .= ">$_";
+ }
+ $return .= "</SELECT>";
+
+ $return;
+}
+
+=item popselector HASHREF | LIST
+
+Takes as input a hashref or list of key/value pairs with the following keys:
+
+=over 4
+
+=item popnum
+
+=item pops - An arrayref of hash references specifying access numbers. Normally you can just pass the value of the I<svc_acct_pop> field returned by B<signup_info>.
+
+=back
+
+Returns an HTML fragment for access number selection.
+
+=cut
+
+#horrible false laziness with FS/FS/svc_acct_pop.pm::popselector
+sub popselector {
+ my $param;
+ if ( ref($_[0]) ) {
+ $param = shift;
+ } else {
+ $param = { @_ };
+ }
+ my $popnum = $param->{'popnum'};
+ my $pops = $param->{'pops'};
+
+ return '<INPUT TYPE="hidden" NAME="popnum" VALUE="">' unless @$pops;
+ return $pops->[0]{city}. ', '. $pops->[0]{state}.
+ ' ('. $pops->[0]{ac}. ')/'. $pops->[0]{exch}. '-'. $pops->[0]{loc}.
+ '<INPUT TYPE="hidden" NAME="popnum" VALUE="'. $pops->[0]{popnum}. '">'
+ if scalar(@$pops) == 1;
+
+ my %pop = ();
+ my %popnum2pop = ();
+ foreach (@$pops) {
+ push @{ $pop{ $_->{state} }->{ $_->{ac} } }, $_;
+ $popnum2pop{$_->{popnum}} = $_;
+ }
+
+ my $text = <<END;
+ <SCRIPT>
+ function opt(what,href,text) {
+ var optionName = new Option(text, href, false, false)
+ var length = what.length;
+ what.options[length] = optionName;
+ }
+END
+
+ my $init_popstate = $param->{'init_popstate'};
+ if ( $init_popstate ) {
+ $text .= '<INPUT TYPE="hidden" NAME="init_popstate" VALUE="'.
+ $init_popstate. '">';
+ } else {
+ $text .= <<END;
+ function acstate_changed(what) {
+ state = what.options[what.selectedIndex].text;
+ what.form.popac.options.length = 0
+ what.form.popac.options[0] = new Option("Area code", "-1", false, true);
+END
+ }
+
+ my @states = $init_popstate ? ( $init_popstate ) : keys %pop;
+ foreach my $state ( sort { $a cmp $b } @states ) {
+ $text .= "\nif ( state == \"$state\" ) {\n" unless $init_popstate;
+
+ foreach my $ac ( sort { $a cmp $b } keys %{ $pop{$state} }) {
+ $text .= "opt(what.form.popac, \"$ac\", \"$ac\");\n";
+ if ($ac eq $param->{'popac'}) {
+ $text .= "what.form.popac.options[what.form.popac.length-1].selected = true;\n";
+ }
+ }
+ $text .= "}\n" unless $init_popstate;
+ }
+ $text .= "popac_changed(what.form.popac)}\n";
+
+ $text .= <<END;
+ function popac_changed(what) {
+ ac = what.options[what.selectedIndex].text;
+ what.form.popnum.options.length = 0;
+ what.form.popnum.options[0] = new Option("City", "-1", false, true);
+
+END
+
+ foreach my $state ( @states ) {
+ foreach my $popac ( keys %{ $pop{$state} } ) {
+ $text .= "\nif ( ac == \"$popac\" ) {\n";
+
+ foreach my $pop ( @{$pop{$state}->{$popac}}) {
+ my $o_popnum = $pop->{popnum};
+ my $poptext = $pop->{city}. ', '. $pop->{state}.
+ ' ('. $pop->{ac}. ')/'. $pop->{exch}. '-'. $pop->{loc};
+
+ $text .= "opt(what.form.popnum, \"$o_popnum\", \"$poptext\");\n";
+ if ($popnum == $o_popnum) {
+ $text .= "what.form.popnum.options[what.form.popnum.length-1].selected = true;\n";
+ }
+ }
+ $text .= "}\n";
+ }
+ }
+
+
+ $text .= "}\n</SCRIPT>\n";
+
+ $text .=
+ qq!<TABLE CELLPADDING="0"><TR><TD><SELECT NAME="acstate"! .
+ qq!SIZE=1 onChange="acstate_changed(this)"><OPTION VALUE=-1>State!;
+ $text .= "<OPTION" . ($_ eq $param->{'acstate'} ? " SELECTED" : "") .
+ ">$_" foreach sort { $a cmp $b } @states;
+ $text .= '</SELECT>'; #callback? return 3 html pieces? #'</TD>';
+
+ $text .=
+ qq!<SELECT NAME="popac" SIZE=1 onChange="popac_changed(this)">!.
+ qq!<OPTION>Area code</SELECT></TR><TR VALIGN="top">!;
+
+ $text .= qq!<TR><TD><SELECT NAME="popnum" SIZE=1 STYLE="width: 20em"><OPTION>City!;
+
+
+ #comment this block to disable initial list polulation
+ my @initial_select = ();
+ if ( scalar( @$pops ) > 100 ) {
+ push @initial_select, $popnum2pop{$popnum} if $popnum2pop{$popnum};
+ } else {
+ @initial_select = @$pops;
+ }
+ foreach my $pop ( sort { $a->{state} cmp $b->{state} } @initial_select ) {
+ $text .= qq!<OPTION VALUE="!. $pop->{popnum}. '"'.
+ ( ( $popnum && $pop->{popnum} == $popnum ) ? ' SELECTED' : '' ). ">".
+ $pop->{city}. ', '. $pop->{state}.
+ ' ('. $pop->{ac}. ')/'. $pop->{exch}. '-'. $pop->{loc};
+ }
+
+ $text .= qq!</SELECT></TD></TR></TABLE>!;
+
+ $text;
+
+}
+
+=back
+
+=head1 RESELLER FUNCTIONS
+
+Note: Resellers can also use the B<signup_info> and B<new_customer> functions
+with their active session.
+
+=over 4
+
+=item agent_login
+
+=item agent_info
+
+=item agent_list_customers
=back
diff --git a/fs_selfservice/FS-SelfService/cgi/agent.cgi b/fs_selfservice/FS-SelfService/cgi/agent.cgi
new file mode 100644
index 000000000..3508e82e3
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/agent.cgi
@@ -0,0 +1,256 @@
+#!/usr/bin/perl -Tw
+
+#some false laziness w/selfservice.cgi
+
+use strict;
+use vars qw($cgi $session_id $form_max $template_dir);
+use subs qw(do_template);
+use CGI;
+use CGI::Carp qw(fatalsToBrowser);
+use Business::CreditCard;
+use Text::Template;
+use FS::SelfService qw( agent_login agent_info
+ agent_list_customers
+ signup_info new_customer
+ customer_info order_pkg
+ );
+
+$template_dir = '.';
+
+$form_max = 255;
+
+$cgi = new CGI;
+
+unless ( defined $cgi->param('session') ) {
+ do_template('agent_login',{});
+ exit;
+}
+
+if ( $cgi->param('session') eq 'login' ) {
+
+ $cgi->param('username') =~ /^\s*([a-z0-9_\-\.\&]{0,$form_max})\s*$/i
+ or die "illegal username";
+ my $username = $1;
+
+ $cgi->param('password') =~ /^(.{0,$form_max})$/
+ or die "illegal password";
+ my $password = $1;
+
+ my $rv = agent_login(
+ 'username' => $username,
+ 'password' => $password,
+ );
+ if ( $rv->{error} ) {
+ do_template('agent_login', {
+ 'error' => $rv->{error},
+ 'username' => $username,
+ } );
+ exit;
+ } else {
+ $cgi->param('session' => $rv->{session_id} );
+ $cgi->param('action' => 'agent_main' );
+ }
+}
+
+$session_id = $cgi->param('session');
+
+$cgi->param('action') =~
+ /^(agent_main|signup|process_signup|list_customers|view_customer|process_order_pkg)$/
+ or die "unknown action ". $cgi->param('action');
+my $action = $1;
+
+warn "running $action\n";
+my $result = eval "&$action();";
+die $@ if $@;
+
+if ( $result->{error} eq "Can't resume session" ) { #ick
+ do_template('agent_login',{});
+ exit;
+}
+
+warn "processing template $action\n";
+do_template($action, {
+ 'session_id' => $session_id,
+ %{$result}
+});
+
+#--
+
+sub agent_main { agent_info( 'session_id' => $session_id ); }
+
+sub signup { signup_info( 'session_id' => $session_id ); }
+
+sub process_signup {
+
+ my $init_data = signup_info( 'session_id' => $session_id );
+ if ( $init_data->{'error'} ) {
+ if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
+ do_template('agent_login',{});
+ exit;
+ } else { #?
+ die $init_data->{'error'};
+ }
+ }
+
+ my $error = '';
+
+ #some false laziness w/signup.cgi
+ my $payby = $cgi->param('payby');
+ if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
+ #$payinfo = join('@', map { $cgi->param( $payby. "_payinfo$_" ) } (1,2) );
+ $cgi->param('payinfo' => $cgi->param($payby. '_payinfo1'). '@'.
+ $cgi->param($payby. '_payinfo2')
+ );
+ } else {
+ $cgi->param('payinfo' => $cgi->param( $payby. '_payinfo' ) );
+ }
+ $cgi->param('paydate' => $cgi->param( $payby. '_month' ). '-'.
+ $cgi->param( $payby. '_year' )
+ );
+ $cgi->param('payname' => $cgi->param( $payby. '_payname' ) );
+ $cgi->param('paycvv' => defined $cgi->param( $payby. '_paycvv' )
+ ? $cgi->param( $payby. '_paycvv' )
+ : ''
+ );
+
+ if ( $cgi->param('invoicing_list') ) {
+ $cgi->param('invoicing_list' => $cgi->param('invoicing_list'). ', POST')
+ if $cgi->param('invoicing_list_POST');
+ } else {
+ $cgi->param('invoicing_list' => 'POST' );
+ }
+
+ if ( $cgi->param('_password') ne $cgi->param('_password2') ) {
+ $error = $init_data->{msgcat}{passwords_dont_match}; #msgcat
+ $cgi->param('_password', '');
+ $cgi->param('_password2', '');
+ }
+
+ if ( $payby =~ /^(CARD|DCRD)$/ && $cgi->param('CARD_type') ) {
+ my $payinfo = $cgi->param('payinfo');
+ $payinfo =~ s/\D//g;
+
+ $payinfo =~ /^(\d{13,16})$/
+ or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ $payinfo = $1;
+ validate($payinfo)
+ or $error ||= $init_data->{msgcat}{invalid_card}; #. $self->payinfo;
+ cardtype($payinfo) eq $cgi->param('CARD_type')
+ or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
+ }
+
+ unless ( $error ) {
+ my $rv = new_customer ( {
+ 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) }
+ qw( last first ss company
+ address1 address2 city county state zip country
+ daytime night fax
+ payby payinfo paycvv paydate payname invoicing_list
+ pkgpart username sec_phrase _password popnum refnum
+ ),
+ grep { /^snarf_/ } $cgi->param
+ } );
+ $error = $rv->{'error'};
+ }
+
+ if ( $error ) {
+ $action = 'signup';
+ my $r = {
+ $cgi->Vars,
+ %{$init_data},
+ 'error' => $error,
+ };
+ #warn join('\n', map "$_ => $r->{$_}", keys %$r )."\n";
+ $r;
+ } else {
+ $action = 'agent_main';
+ my $agent_info = agent_info( 'session_id' => $session_id );
+ $agent_info->{'message'} = 'Signup sucessful';
+ $agent_info;
+ }
+
+}
+
+sub list_customers {
+ agent_list_customers( 'session_id' => $session_id,
+ map { $_ => $cgi->param($_) }
+ grep defined($cgi->param($_)),
+ qw(prospect active susp cancel)
+ );
+}
+
+sub view_customer {
+
+ my $init_data = signup_info( 'session_id' => $session_id );
+ if ( $init_data->{'error'} ) {
+ if ( $init_data->{'error'} eq "Can't resume session" ) { #ick
+ do_template('agent_login',{});
+ exit;
+ } else { #?
+ die $init_data->{'error'};
+ }
+ }
+
+ my $customer_info = customer_info (
+ 'agent_session_id' => $session_id,
+ 'custnum' => $cgi->param('custnum')
+ );
+
+
+ return {
+ ( map { $_ => $init_data->{$_} }
+ qw( part_pkg security_phrase svc_acct_pop ),
+ ),
+ %$customer_info,
+ };
+}
+
+sub process_order_pkg {
+
+ my $results = order_pkg (
+ 'agent_session_id' => $session_id,
+ map { $_ => $cgi->param($_) }
+ qw( custnum pkgpart username _password _password2 sec_phrase popnum )
+ );
+
+ $action = 'view_customer';
+ $cgi->delete( grep { $_ ne 'custnum' } $cgi->param )
+ unless $results->{'error'};
+
+ return {
+ $cgi->Vars,
+ %{view_customer()},
+ 'message' => $results->{'error'}
+ ? '<FONT COLOR="#FF0000">'. $results->{'error'}. '</FONT>'
+ : 'Package order sucessful.'
+ };
+
+}
+
+#--
+
+sub do_template {
+ my $name = shift;
+ my $fill_in = shift;
+ #warn join(' / ', map { "$_=>".$fill_in->{$_} } keys %$fill_in). "\n";
+
+ $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",
+ DELIMITERS => [ '<%=', '%>' ],
+ UNTAINT => 1, )
+ or die $Text::Template::ERROR;
+
+ print $cgi->header( '-expires' => 'now' ),
+ $template->fill_in( PACKAGE => 'FS::SelfService::_agentcgi',
+ HASH => $fill_in
+ );
+}
+
+package FS::SelfService::_agentcgi;
+use FS::SelfService qw(regionselector expselect popselector);
+
diff --git a/fs_selfservice/FS-SelfService/cgi/agent_login.html b/fs_selfservice/FS-SelfService/cgi/agent_login.html
new file mode 100644
index 000000000..4b0778ec5
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/agent_login.html
@@ -0,0 +1,22 @@
+<HTML><HEAD><TITLE>Reseller Login</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=5>Reseller Login</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM ACTION="<%= $self_url %>" METHOD=POST>
+<INPUT TYPE="hidden" NAME="session" VALUE="login">
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=2 CELLPADDING=0>
+<TR>
+ <TH ALIGN="right">Username </TH>
+ <TD>
+ <INPUT TYPE="text" NAME="username" VALUE="<%= $username %>">
+ </TD>
+</TR>
+<TR>
+ <TH ALIGN="right">Password </TH>
+ <TD>
+ <INPUT TYPE="password" NAME="password">
+ </TD>
+</TR>
+</TABLE>
+<BR><BR><INPUT TYPE="submit" VALUE="Login">
+</FORM></BODY></HTML>
+
diff --git a/fs_selfservice/FS-SelfService/cgi/agent_main.html b/fs_selfservice/FS-SelfService/cgi/agent_main.html
new file mode 100644
index 000000000..89a1b330d
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/agent_main.html
@@ -0,0 +1,40 @@
+<HTML><HEAD><TITLE>Reseller Main</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>Reseller Main</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 %>agent_main">Reseller Main</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
+</TD><TD VALIGN="top">
+
+<%= $message
+ ? "<FONT SIZE=\"+2\"><B>$message</B></FONT>"
+ : "Hello $agent!"
+%><BR><BR>
+
+<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#eeeeee">
+<TR><TH BGCOLOR="#cccccc">Customer summary</TH></TR>
+<TR><TD BGCOLOR="#dddddd">
+
+ <B><%= $num_prospect %></B>
+ <A HREF="<%= $url %>list_customers&prospect=1">prospects</A>
+
+ <BR><FONT COLOR="#00CC00"><B><%= $num_active %></B></FONT>
+ <A HREF="<%= $url %>list_customers&active=1">active</A>
+
+ <BR><FONT COLOR="#FF9900"><B><%= $num_susp %></B></FONT>
+ <A HREF="<%= $url %>list_customers&susp=1">suspended</A>
+
+ <BR><FONT COLOR="#FF0000"><B><%= $num_cancel %></B></FONT>
+ <A HREF="<%= $url %>list_customers&cancel=1">cancelled</A>
+
+</TD></TR></TABLE>
+
+<BR><A HREF="<%= $url %>signup">New customer<!--/prospect--></A>
+
+</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/cvv2.html b/fs_selfservice/FS-SelfService/cgi/cvv2.html
new file mode 100644
index 000000000..b178c8513
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/cvv2.html
@@ -0,0 +1,25 @@
+<HTML>
+ <HEAD>
+ <TITLE>
+ CVV2 information
+ </TITLE>
+ </HEAD>
+ <BODY BGCOLOR="#e8e8e8">
+ The CVV2 number (also called CVC2 or CID) is a three- or four-digit
+ security code used to reduce credit card fraud.<BR><BR>
+ <TABLE BORDER=0 CELLSPACING=4>
+ <TR>
+ <TH>Visa / MasterCard / Discover</TH>
+ <TH>American Express</TH>
+ </TR>
+ <TR>
+ <TD>
+ <IMG BORDER=0 ALT="Visa/MasterCard/Discover" SRC="cvv2.png">
+ </TD>
+ <TD>
+ <IMG BORDER=0 ALT="American Express" SRC="cvv2_amex.png">
+ </TD>
+ </TABLE>
+ <CENTER><A HREF="javascript:close()">(close window)</A></CENTER>
+ </BODY>
+</HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/cvv2.png b/fs_selfservice/FS-SelfService/cgi/cvv2.png
new file mode 100644
index 000000000..4610dcbe6
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/cvv2.png
Binary files differ
diff --git a/fs_selfservice/FS-SelfService/cgi/cvv2_amex.png b/fs_selfservice/FS-SelfService/cgi/cvv2_amex.png
new file mode 100644
index 000000000..21c36a0ab
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/cvv2_amex.png
Binary files differ
diff --git a/fs_selfservice/FS-SelfService/cgi/list_customers.html b/fs_selfservice/FS-SelfService/cgi/list_customers.html
new file mode 100644
index 000000000..6d4ba564e
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/list_customers.html
@@ -0,0 +1,41 @@
+<HTML><HEAD><TITLE>Reseller Main</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>Reseller Main</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 %>agent_main">Reseller Main</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
+</TD><TD VALIGN="top">
+
+<%=
+ if ( @customers ) {
+ $OUT .= '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=2 BGCOLOR="#eeeeee">'.
+ '<TR><TH BGCOLOR="#cccccc" COLSPAN=3>Customers</TH><TD>';
+ my $col1 = "ffffff";
+ my $col2 = "dddddd";
+ my $col = $col1;
+
+ foreach my $customer ( @customers ) {
+ my $td = qq!<TD BGCOLOR="#$col">!;
+ my $a = qq!<A HREF="${url}view_customer;custnum=!.
+ $customer->{'custnum'}. '">';
+ $OUT .=
+ '<TR>'.
+ "$td<FONT COLOR=\"". $customer->{'statuscolor'}. '">'.
+ ucfirst($customer->{'status'}). "</TD>". "$td</TD>".
+ "$td$a". $customer->{'name'}. "</A></TD>".
+ '</TR>';
+ #"$td</TD>".
+ $col = $col eq $col1 ? $col2 : $col1;
+ }
+ $OUT .= '</TABLE>';
+ } else {
+ $OUT .= 'No customers.<BR><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/signup.html b/fs_selfservice/FS-SelfService/cgi/signup.html
new file mode 100755
index 000000000..973035179
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/signup.html
@@ -0,0 +1,233 @@
+<HTML><HEAD><TITLE><%= $agent || 'ISP' %> Signup form</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8" onUnload="myclose()">
+<script language="JavaScript"><!--
+ var mywindow = -1;
+ function myopen(filename,windowname,properties) {
+ myclose();
+ mywindow = window.open(filename,windowname,properties);
+ }
+ function myclose() {
+ if ( mywindow != -1 )
+ mywindow.close();
+ mywindow = -1
+ }
+//--></script>
+<FONT SIZE=7><%= $agent || 'ISP' %> Signup form</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM ACTION="<%= $selfurl %>" METHOD=POST>
+<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
+<INPUT TYPE="hidden" NAME="action" VALUE="process_signup">
+<INPUT TYPE="hidden" NAME="ref" VALUE="<%= $referral_custnum %>">
+<INPUT TYPE="hidden" NAME="ss" VALUE="">
+Where did you hear about our service? <SELECT NAME="refnum">
+<%=
+ $OUT .= '<OPTION VALUE="">' unless $refnum;
+ foreach my $part_referral ( @part_referral ) {
+ $OUT .= '<OPTION VALUE="'. $part_referral->{'refnum'}. '"';
+ $OUT .= ' SELECTED' if $part_referral->{'refnum'} eq $refnum;
+ $OUT .= '>'. $part_referral->{'referral'};
+ }
+%>
+</SELECT><BR><BR>
+Contact Information
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR>
+ <TH ALIGN="right"><font color="#ff0000">*</font>Contact name<BR>(last, first)</TH>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="last" VALUE="<%= $last %>">,
+ <INPUT TYPE="text" NAME="first" VALUE="<%= $first %>"></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Company</TD>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="company" SIZE=70 VALUE="<%= $company %>"></TD>
+</TR>
+<TR>
+ <TH ALIGN="right"><font color="#ff0000">*</font>Address</TH>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="address1" SIZE=70 VALUE="<%= $address1 %>"></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">&nbsp;</TD>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="address2" SIZE=70 VALUE="<%= $address2 %>"></TD>
+</TR>
+<TR>
+ <TH ALIGN="right"><font color="#ff0000">*</font>City</TH>
+ <TD><INPUT TYPE="text" NAME="city" VALUE="<%= $city %>"></TD>
+ <TH ALIGN="right"><font color="#ff0000">*</font>State/Country</TH>
+ <TD>
+ <%=
+ ($county_html, $state_html, $country_html) =
+ regionselector( {
+ selected_county => $county,
+ selected_state => $state,
+ selected_country => $country,
+ default_state => $statedefault,
+ default_country => $countrydefault,
+ locales => \@cust_main_county,
+ } );
+
+ "$county_html $state_html";
+ %>
+ </TD>
+ <TH><font color="#ff0000">*</font>Zip</TH>
+ <TD><INPUT TYPE="text" NAME="zip" SIZE=10 VALUE="<%= $zip %>"></TD>
+</TR>
+<TR>
+ <TH ALIGN="right"><font color="#ff0000">*</font>Country</TH>
+ <TD><%= $country_html %></TD>
+<TR>
+ <TD ALIGN="right">Day Phone</TD>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="daytime" VALUE="<%= $daytime %>" SIZE=18></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Night Phone</TD>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="night" VALUE="<%= $night %>" SIZE=18></TD>
+</TR>
+<TR>
+ <TD ALIGN="right">Fax</TD>
+ <TD COLSPAN=5><INPUT TYPE="text" NAME="fax" VALUE="<%= $fax %>" SIZE=12></TD>
+</TR>
+</TABLE><font color="#ff0000">*</font> required fields<BR>
+<BR>Billing information<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR><TD>
+
+ <%=
+ $OUT .= '<INPUT TYPE="checkbox" NAME="invoicing_list_POST" VALUE="POST"';
+ my @invoicing_list = split(', ', $invoicing_list );
+ $OUT .= ' CHECKED'
+ if ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list;
+ $OUT .= '>';
+ %>
+
+ Postal mail invoice
+</TD></TR>
+<TR><TD>Email invoice <INPUT TYPE="text" NAME="invoicing_list" VALUE="<%= join(', ', grep { $_ ne 'POST' } split(', ', $invoicing_list ) ) %>">
+</TD></TR>
+<%= scalar(@payby) > 1 ? '<TR><TD>Billing type</TD></TR>' : '' %>
+</TABLE>
+<TABLE BGCOLOR="#c0c0c0" BORDER=1 WIDTH="100%">
+<TR>
+
+ <%=
+
+ my $cardselect = '<SELECT NAME="CARD_type"><OPTION></OPTION>';
+ my %types = (
+ 'VISA' => 'VISA card',
+ 'MasterCard' => 'MasterCard',
+ 'Discover' => 'Discover card',
+ 'American Express' => 'American Express card',
+ );
+ foreach ( keys %types ) {
+ $selected = $CARD_type eq $types{$_} ? 'SELECTED' : '';
+ $cardselect .= qq!<OPTION $selected VALUE="$types{$_}">$_</OPTION>!;
+ }
+ $cardselect .= '</SELECT>';
+
+ my %payby = (
+ 'CARD' => qq!Credit card<BR><font color="#ff0000">*</font>$cardselect<INPUT TYPE="text" NAME="CARD_payinfo" VALUE="" MAXLENGTH=19><BR><font color="#ff0000">*</font>Exp !. expselect("CARD"). qq!<BR><font color="#ff0000">*</font>Name on card<BR><INPUT TYPE="text" NAME="CARD_payname" VALUE="">!,
+ 'DCRD' => qq!Credit card<BR><font color="#ff0000">*</font>$cardselect<INPUT TYPE="text" NAME="DCRD_payinfo" VALUE="" MAXLENGTH=19><BR><font color="#ff0000">*</font>Exp !. expselect("DCRD"). qq!<BR><font color="#ff0000">*</font>Name on card<BR><INPUT TYPE="text" NAME="DCRD_payname" VALUE="">!,
+ 'CHEK' => qq!Electronic check<BR>${r}Account number <INPUT TYPE="text" NAME="CHEK_payinfo1" VALUE="" MAXLENGTH=10><BR>${r}ABA/Routing code <INPUT TYPE="text" NAME="CHEK_payinfo2" VALUE="" SIZE=10 MAXLENGTH=9><INPUT TYPE="hidden" NAME="CHEK_month" VALUE="12"><INPUT TYPE="hidden" NAME="CHEK_year" VALUE="2037"><BR>${r}Bank name <INPUT TYPE="text" NAME="CHEK_payname" VALUE="">!,
+ 'DCHK' => qq!Electronic check<BR>${r}Account number <INPUT TYPE="text" NAME="DCHK_payinfo1" VALUE="" MAXLENGTH=10><BR>${r}ABA/Routing code <INPUT TYPE="text" NAME="DCHK_payinfo2" VALUE="" SIZE=10 MAXLENGTH=9><INPUT TYPE="hidden" NAME="DCHK_month" VALUE="12"><INPUT TYPE="hidden" NAME="DCHK_year" VALUE="2037"><BR>${r}Bank name <INPUT TYPE="text" NAME="DCHK_payname" VALUE="">!,
+ 'LECB' => qq!Phone bill billing<BR>${r}Phone number <INPUT TYPE="text" BANE="LECB_payinfo" VALUE="" MAXLENGTH=15 SIZE=16><INPUT TYPE="hidden" NAME="LECB_month" VALUE="12"><INPUT TYPE="hidden" NAME="LECB_year" VALUE="2037"><INPUT TYPE="hidden" NAME="LECB_payname" VALUE="">!,
+ 'BILL' => qq!Billing<BR>P.O. <INPUT TYPE="text" NAME="BILL_payinfo" VALUE=""><BR><font color="#ff0000">*</font>Exp !. expselect("BILL", "12-2037"). qq!<BR><font color="#ff0000">*</font>Attention<BR><INPUT TYPE="text" NAME="BILL_payname" VALUE="Accounts Payable">!,
+ 'COMP' => qq!Complimentary<BR><font color="#ff0000">*</font>Approved by<INPUT TYPE="text" NAME="COMP_payinfo" VALUE=""><BR><font color="#ff0000">*</font>Exp !. expselect("COMP"),
+ 'PREPAY' => qq!Prepaid card<BR><font color="#ff0000">*</font><INPUT TYPE="text" NAME="PREPAY_payinfo" VALUE="" MAXLENGTH=80>!,
+ );
+
+ if ( $cvv_enabled ) {
+ foreach my $payby ( grep { exists $payby{$_} } qw(CARD DCRD) ) { #1.4/1.5
+ $payby{$payby} .= qq!<BR>CVV2&nbsp;(<A HREF="javascript:myopen('cvv2.html','cvv2','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,width=480,height=288')">help</A>)&nbsp;<INPUT TYPE="text" NAME=${payby}_paycvv VALUE="" SIZE=4 MAXLENGTH=4>!;
+ }
+ }
+
+ my( $account, $aba ) = split('@', $payinfo);
+ my %paybychecked = (
+ 'CARD' => qq!Credit card<BR><font color="#ff0000">*</font>$cardselect<INPUT TYPE="text" NAME="CARD_payinfo" VALUE="$payinfo" MAXLENGTH=19><BR><font color="#ff0000">*</font>Exp !. expselect("CARD", $paydate). qq!<BR><font color="#ff0000">*</font>Name on card<BR><INPUT TYPE="text" NAME="CARD_payname" VALUE="$payname">!,
+ 'DCRD' => qq!Credit card<BR><font color="#ff0000">*</font>$cardselect<INPUT TYPE="text" NAME="DCRD_payinfo" VALUE="$payinfo" MAXLENGTH=19><BR><font color="#ff0000">*</font>Exp !. expselect("DCRD", $paydate). qq!<BR><font color="#ff0000">*</font>Name on card<BR><INPUT TYPE="text" NAME="DCRD_payname" VALUE="$payname">!,
+ 'CHEK' => qq!Electronic check<BR>${r}Account number <INPUT TYPE="text" NAME="CHEK_payinfo1" VALUE="$account" MAXLENGTH=10><BR>${r}ABA/Routing code <INPUT TYPE="text" NAME="CHEK_payinfo2" VALUE="$aba" SIZE=10 MAXLENGTH=9><INPUT TYPE="hidden" NAME="CHEK_month" VALUE="12"><INPUT TYPE="hidden" NAME="CHEK_year" VALUE="2037"><BR>${r}Bank name <INPUT TYPE="text" NAME="CHEK_payname" VALUE="$payname">!,
+ 'DCHK' => qq!Electronic check<BR>${r}Account number <INPUT TYPE="text" NAME="DCHK_payinfo1" VALUE="$account" MAXLENGTH=10><BR>${r}ABA/Routing code <INPUT TYPE="text" NAME="DCHK_payinfo2" VALUE="$aba" SIZE=10 MAXLENGTH=9><INPUT TYPE="hidden" NAME="DCHK_month" VALUE="12"><INPUT TYPE="hidden" NAME="DCHK_year" VALUE="2037"><BR>${r}Bank name <INPUT TYPE="text" NAME="DCHK_payname" VALUE="$payname">!,
+ 'LECB' => qq!Phone bill billing<BR>${r}Phone number <INPUT TYPE="text" BANE="LECB_payinfo" VALUE="$payinfo" MAXLENGTH=15 SIZE=16><INPUT TYPE="hidden" NAME="LECB_month" VALUE="12"><INPUT TYPE="hidden" NAME="LECB_year" VALUE="2037"><INPUT TYPE="hidden" NAME="LECB_payname" VALUE="">!,
+ 'BILL' => qq!Billing<BR>P.O. <INPUT TYPE="text" NAME="BILL_payinfo" VALUE="$payinfo"><BR><font color="#ff0000">*</font>Exp !. expselect("BILL", $paydate). qq!<BR><font color="#ff0000">*</font>Attention<BR><INPUT TYPE="text" NAME="BILL_payname" VALUE="$payname">!,
+ 'COMP' => qq!Complimentary<BR><font color="#ff0000">*</font>Approved by<INPUT TYPE="text" NAME="COMP_payinfo" VALUE="$payinfo"><BR><font color="#ff0000">*</font>Exp !. expselect("COMP", $paydate),
+ 'PREPAY' => qq!Prepaid card<BR><font color="#ff0000">*</font><INPUT TYPE="text" NAME="PREPAY_payinfo" VALUE="$payinfo" MAXLENGTH=80>!,
+ );
+
+ if ( $cvv_enabled ) {
+ foreach my $payby ( grep { exists $payby{$_} } qw(CARD DCRD) ) { #1.4/1.5
+ $paybychecked{$payby} .= qq!<BR>CVV2&nbsp;(<A HREF="javascript:myopen('cvv2.html','cvv2','toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,resizable=yes,copyhistory=no,width=480,height=288')">help</A>)&nbsp;<INPUT TYPE="text" NAME=${payby}_paycvv VALUE="$paycvv" SIZE=4 MAXLENGTH=4>!;
+ }
+ }
+
+ for (@payby) {
+ if ( scalar(@payby) == 1) {
+ $OUT .= '<TD VALIGN=TOP>'.
+ qq!<INPUT TYPE="hidden" NAME="payby" VALUE="$_">!.
+ "$paybychecked{$_}</TD>";
+ } else {
+ $OUT .= qq!<TD VALIGN=TOP><INPUT TYPE="radio" NAME="payby" VALUE="$_"!;
+ if ($payby eq $_) {
+ $OUT .= qq! CHECKED> $paybychecked{$_}</TD>!;
+ } else {
+ $OUT .= qq!> $payby{$_}</TD>!;
+ }
+
+ }
+ }
+ %>
+
+</TR></TABLE><font color="#ff0000">*</font> required fields for each billing type
+<BR><BR>First package
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR>
+ <TD COLSPAN=2><SELECT NAME="pkgpart"><OPTION VALUE="">(none)
+
+ <%=
+ foreach my $part_pkg ( @part_pkg ) {
+ $OUT .= '<OPTION VALUE="'. $part_pkg->{'pkgpart'}. '"';
+ $OUT .= ' SELECTED' if $pkgpart && $part_pkg->{'pkgpart'} == $pkgpart;
+ $OUT .= '>'. $part_pkg->{'pkg'};
+ }
+ %>
+
+ </SELECT></TD>
+</TR>
+<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>
+<BR><BR><INPUT TYPE="submit" VALUE="Signup">
+</FORM></BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/view_customer.html b/fs_selfservice/FS-SelfService/cgi/view_customer.html
new file mode 100644
index 000000000..e4e9be250
--- /dev/null
+++ b/fs_selfservice/FS-SelfService/cgi/view_customer.html
@@ -0,0 +1,84 @@
+<HTML><HEAD><TITLE>View Customer</TITLE></HEAD>
+<BODY BGCOLOR="#eeeeee"><FONT SIZE=5>View Customer</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 %>agent_main">Reseller Main</A><BR>
+<!-- <A HREF="<%= $url %>other">SomethingElse</A><BR> -->
+</TD><TD VALIGN="top">
+
+<%= $message
+ ? "<FONT SIZE=\"+2\"><B>$message</B></FONT><BR><BR>"
+ : ''
+%>
+
+<%= $small_custview %>
+
+<BR>Purchase additional package
+<FORM ACTION="<%= $selfurl %>" METHOD=POST>
+<INPUT TYPE="hidden" NAME="session" VALUE="<%= $session_id %>">
+<INPUT TYPE="hidden" NAME="action" VALUE="process_order_pkg">
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>">
+<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
+<TR>
+ <TD COLSPAN=2><SELECT NAME="pkgpart"><OPTION VALUE="">
+
+ <%=
+ foreach my $part_pkg ( @part_pkg ) {
+ $OUT .= '<OPTION VALUE="'. $part_pkg->{'pkgpart'}. '"';
+ $OUT .= ' SELECTED' if $pkgpart && $part_pkg->{'pkgpart'} == $pkgpart;
+ $OUT .= '>'. $part_pkg->{'pkg'};
+ }
+ %>
+
+ </SELECT></TD>
+</TR>
+<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="Purchase">
+</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_signup/FS-SignupClient/SignupClient.pm b/fs_signup/FS-SignupClient/SignupClient.pm
index fb2b12fb0..b646baca2 100644
--- a/fs_signup/FS-SignupClient/SignupClient.pm
+++ b/fs_signup/FS-SignupClient/SignupClient.pm
@@ -1,7 +1,7 @@
package FS::SignupClient;
use strict;
-use vars qw($VERSION @ISA @EXPORT_OK); # $fs_signupd_socket);
+use vars qw($VERSION @ISA @EXPORT_OK $init_data); # $fs_signupd_socket);
use Exporter;
#use Socket;
#use FileHandle;
@@ -12,7 +12,7 @@ use FS::SelfService; # qw( new_customer signup_info );
$VERSION = '0.04';
@ISA = qw( Exporter );
-@EXPORT_OK = qw( signup_info new_customer );
+@EXPORT_OK = qw( signup_info new_customer regionselector );
=head1 NAME
@@ -99,7 +99,7 @@ Each hash reference has the following keys:
#compatibility bit
sub signup_info {
- my $init_data = FS::SelfService::signup_info();
+ $init_data = FS::SelfService::signup_info();
(map { $init_data->{$_} } qw( cust_main_county part_pkg svc_acct_pop ) ),
$init_data;
@@ -148,10 +148,56 @@ sub new_customer {
$hash->{'error'};
}
+=item regionselector SELECTED_COUNTY, SELECTED_STATE, SELECTED_COUNTRY, PREFIX, ONCHANGE
+
+=cut
+
+sub regionselector {
+ my ( $selected_county, $selected_state, $selected_country,
+ $prefix, $onchange ) = @_;
+ signup_info() unless $init_data;
+ FS::SelfService::regionselector({
+ selected_county => $selected_county,
+ selected_state => $selected_state,
+ selected_country => $selected_country,
+ prefix => $prefix,
+ onchange => $onchange,
+ default_country => $init_data->{countrydefault},
+ locales => $init_data->{cust_main_county},
+ });
+ #default_state => $init_data->{statedefault},
+}
+
+=item expselect PREFIX, DATE
+
+=cut
+
+sub expselect {
+ FS::SelfService::expselect(@_);
+}
+
+=item popselector
+
+=cut
+
+sub popselector {
+ my( $popnum ) = @_;
+ signup_info() unless $init_data;
+ FS::SelfService::popselector({
+ popnum => $popnum,
+ pops => $init_data->{svc_acct_pop},
+ });
+ #popac =>
+ #acstate =>
+}
+
=back
=head1 BUGS
+This is just a wrapper around FS::SelfService functions for backwards
+compatibility and will probably be deprecated soon.
+
=head1 SEE ALSO
L<fs_signupd>, L<FS::cust_main>
diff --git a/fs_signup/FS-SignupClient/cgi/signup.cgi b/fs_signup/FS-SignupClient/cgi/signup.cgi
index 0a9a51008..00a7aa61e 100755
--- a/fs_signup/FS-SignupClient/cgi/signup.cgi
+++ b/fs_signup/FS-SignupClient/cgi/signup.cgi
@@ -1,6 +1,6 @@
#!/usr/bin/perl -Tw
#
-# $Id: signup.cgi,v 1.50 2004-01-04 03:52:54 ivan Exp $
+# $Id: signup.cgi,v 1.51 2004-06-10 12:31:32 ivan Exp $
use strict;
use vars qw( @payby $cgi $locales $packages
@@ -20,14 +20,14 @@ use vars qw( @payby $cgi $locales $packages
$self_url
);
use subs qw( print_form print_okay print_decline
- success_default decline_default
- expselect );
+ success_default decline_default );
use CGI;
#use CGI::Carp qw(fatalsToBrowser);
use Text::Template;
use Business::CreditCard;
use HTTP::BrowserDetect;
-use FS::SignupClient 0.03 qw( signup_info new_customer );
+use FS::SignupClient 0.03 qw( signup_info new_customer
+ regionselector expselect popselector);
#acceptable payment methods
#
@@ -360,265 +360,6 @@ sub print_okay {
}
}
-#horrible false laziness with FS/FS/svc_acct_pop.pm::popselector
-sub popselector {
-
- my( $popnum ) = @_;
-
- return '<INPUT TYPE="hidden" NAME="popnum" VALUE="">' unless @$pops;
- return $pops->[0]{city}. ', '. $pops->[0]{state}.
- ' ('. $pops->[0]{ac}. ')/'. $pops->[0]{exch}. '-'. $pops->[0]{loc}.
- '<INPUT TYPE="hidden" NAME="popnum" VALUE="'. $pops->[0]{popnum}. '">'
- if scalar(@$pops) == 1;
-
- #my %pop = ();
- #my %popnum2pop = ();
- #foreach (@$pops) {
- # push @{ $pop{ $_->{state} }->{ $_->{ac} } }, $_;
- # $popnum2pop{$_->{popnum}} = $_;
- #}
-
- my $text = <<END;
- <SCRIPT>
- function opt(what,href,text) {
- var optionName = new Option(text, href, false, false)
- var length = what.length;
- what.options[length] = optionName;
- }
-END
-
- if ( $init_popstate ) {
- $text .= '<INPUT TYPE="hidden" NAME="init_popstate" VALUE="'.
- $init_popstate. '">';
- } else {
- $text .= <<END;
- function acstate_changed(what) {
- state = what.options[what.selectedIndex].text;
- what.form.popac.options.length = 0
- what.form.popac.options[0] = new Option("Area code", "-1", false, true);
-END
- }
-
- my @states = $init_popstate ? ( $init_popstate ) : keys %pop;
- foreach my $state ( sort { $a cmp $b } @states ) {
- $text .= "\nif ( state == \"$state\" ) {\n" unless $init_popstate;
-
- foreach my $ac ( sort { $a cmp $b } keys %{ $pop{$state} }) {
- $text .= "opt(what.form.popac, \"$ac\", \"$ac\");\n";
- if ($ac eq $cgi->param('popac')) {
- $text .= "what.form.popac.options[what.form.popac.length-1].selected = true;\n";
- }
- }
- $text .= "}\n" unless $init_popstate;
- }
- $text .= "popac_changed(what.form.popac)}\n";
-
- $text .= <<END;
- function popac_changed(what) {
- ac = what.options[what.selectedIndex].text;
- what.form.popnum.options.length = 0;
- what.form.popnum.options[0] = new Option("City", "-1", false, true);
-
-END
-
- foreach my $state ( @states ) {
- foreach my $popac ( keys %{ $pop{$state} } ) {
- $text .= "\nif ( ac == \"$popac\" ) {\n";
-
- foreach my $pop ( @{$pop{$state}->{$popac}}) {
- my $o_popnum = $pop->{popnum};
- my $poptext = $pop->{city}. ', '. $pop->{state}.
- ' ('. $pop->{ac}. ')/'. $pop->{exch}. '-'. $pop->{loc};
-
- $text .= "opt(what.form.popnum, \"$o_popnum\", \"$poptext\");\n";
- if ($popnum == $o_popnum) {
- $text .= "what.form.popnum.options[what.form.popnum.length-1].selected = true;\n";
- }
- }
- $text .= "}\n";
- }
- }
-
-
- $text .= "}\n</SCRIPT>\n";
-
- $text .=
- qq!<TABLE CELLPADDING="0"><TR><TD><SELECT NAME="acstate"! .
- qq!SIZE=1 onChange="acstate_changed(this)"><OPTION VALUE=-1>State!;
- $text .= "<OPTION" . ($_ eq $cgi->param('acstate') ? " SELECTED" : "") .
- ">$_" foreach sort { $a cmp $b } @states;
- $text .= '</SELECT>'; #callback? return 3 html pieces? #'</TD>';
-
- $text .=
- qq!<SELECT NAME="popac" SIZE=1 onChange="popac_changed(this)">!.
- qq!<OPTION>Area code</SELECT></TR><TR VALIGN="top">!;
-
- $text .= qq!<TR><TD><SELECT NAME="popnum" SIZE=1 STYLE="width: 20em"><OPTION>City!;
-
-
- #comment this block to disable initial list polulation
- my @initial_select = ();
- if ( scalar( @$pops ) > 100 ) {
- push @initial_select, $popnum2pop{$popnum} if $popnum2pop{$popnum};
- } else {
- @initial_select = @$pops;
- }
- foreach my $pop ( sort { $a->{state} cmp $b->{state} } @initial_select ) {
- $text .= qq!<OPTION VALUE="!. $pop->{popnum}. '"'.
- ( ( $popnum && $pop->{popnum} == $popnum ) ? ' SELECTED' : '' ). ">".
- $pop->{city}. ', '. $pop->{state}.
- ' ('. $pop->{ac}. ')/'. $pop->{exch}. '-'. $pop->{loc};
- }
-
- $text .= qq!</SELECT></TD></TR></TABLE>!;
-
- $text;
-
-}
-
-sub expselect {
- my $prefix = shift;
- my $date = shift || '';
- my( $m, $y ) = ( 0, 0 );
- if ( $date =~ /^(\d{4})-(\d{2})-\d{2}$/ ) { #PostgreSQL date format
- ( $m, $y ) = ( $2, $1 );
- } elsif ( $date =~ /^(\d{1,2})-(\d{1,2}-)?(\d{4}$)/ ) {
- ( $m, $y ) = ( $1, $3 );
- }
- my $return = qq!<SELECT NAME="$prefix!. qq!_month" SIZE="1">!;
- for ( 1 .. 12 ) {
- $return .= "<OPTION";
- $return .= " SELECTED" if $_ == $m;
- $return .= ">$_";
- }
- $return .= qq!</SELECT>/<SELECT NAME="$prefix!. qq!_year" SIZE="1">!;
- for ( 2001 .. 2037 ) {
- $return .= "<OPTION";
- $return .= " SELECTED" if $_ == $y;
- $return .= ">$_";
- }
- $return .= "</SELECT>";
-
- $return;
-}
-
-#false laziness w/FS::cust_main_county
-sub regionselector {
- my ( $selected_county, $selected_state, $selected_country,
- $prefix, $onchange ) = @_;
-
- $prefix = '' unless defined $prefix;
-
- my $countyflag = 0;
-
- my %cust_main_county;
-
-# unless ( @cust_main_county ) { #cache
- #@cust_main_county = qsearch('cust_main_county', {} );
- #foreach my $c ( @cust_main_county ) {
- foreach my $c ( @$locales ) {
- #$countyflag=1 if $c->county;
- $countyflag=1 if $c->{county};
- #push @{$cust_main_county{$c->country}{$c->state}}, $c->county;
- #$cust_main_county{$c->country}{$c->state}{$c->county} = 1;
- $cust_main_county{$c->{country}}{$c->{state}}{$c->{county}} = 1;
- }
-# }
- $countyflag=1 if $selected_county;
-
- my $script_html = <<END;
- <SCRIPT>
- function opt(what,value,text) {
- var optionName = new Option(text, value, false, false);
- var length = what.length;
- what.options[length] = optionName;
- }
- function ${prefix}country_changed(what) {
- country = what.options[what.selectedIndex].text;
- for ( var i = what.form.${prefix}state.length; i >= 0; i-- )
- what.form.${prefix}state.options[i] = null;
-END
- #what.form.${prefix}state.options[0] = new Option('', '', false, true);
-
- foreach my $country ( sort keys %cust_main_county ) {
- $script_html .= "\nif ( country == \"$country\" ) {\n";
- foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
- my $text = $state || '(n/a)';
- $script_html .= qq!opt(what.form.${prefix}state, "$state", "$text");\n!;
- }
- $script_html .= "}\n";
- }
-
- $script_html .= <<END;
- }
- function ${prefix}state_changed(what) {
-END
-
- if ( $countyflag ) {
- $script_html .= <<END;
- state = what.options[what.selectedIndex].text;
- country = what.form.${prefix}country.options[what.form.${prefix}country.selectedIndex].text;
- for ( var i = what.form.${prefix}county.length; i >= 0; i-- )
- what.form.${prefix}county.options[i] = null;
-END
-
- foreach my $country ( sort keys %cust_main_county ) {
- $script_html .= "\nif ( country == \"$country\" ) {\n";
- foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
- $script_html .= "\nif ( state == \"$state\" ) {\n";
- #foreach my $county ( sort @{$cust_main_county{$country}{$state}} ) {
- foreach my $county ( sort keys %{$cust_main_county{$country}{$state}} ) {
- my $text = $county || '(n/a)';
- $script_html .=
- qq!opt(what.form.${prefix}county, "$county", "$text");\n!;
- }
- $script_html .= "}\n";
- }
- $script_html .= "}\n";
- }
- }
-
- $script_html .= <<END;
- }
- </SCRIPT>
-END
-
- my $county_html = $script_html;
- if ( $countyflag ) {
- $county_html .= qq!<SELECT NAME="${prefix}county" onChange="$onchange">!;
- $county_html .= '</SELECT>';
- } else {
- $county_html .=
- qq!<INPUT TYPE="hidden" NAME="${prefix}county" VALUE="$selected_county">!;
- }
-
- my $state_html = qq!<SELECT NAME="${prefix}state" !.
- qq!onChange="${prefix}state_changed(this); $onchange">!;
- foreach my $state ( sort keys %{ $cust_main_county{$selected_country} } ) {
- my $text = $state || '(n/a)';
- my $selected = $state eq $selected_state ? 'SELECTED' : '';
- $state_html .= "\n<OPTION $selected VALUE=$state>$text</OPTION>"
- }
- $state_html .= '</SELECT>';
-
- $state_html .= '</SELECT>';
-
- my $country_html = qq!<SELECT NAME="${prefix}country" !.
- qq!onChange="${prefix}country_changed(this); $onchange">!;
- my $countrydefault = $init_data->{countrydefault} || 'US';
- foreach my $country (
- sort { ($b eq $countrydefault) <=> ($a eq $countrydefault) or $a cmp $b }
- keys %cust_main_county
- ) {
- my $selected = $country eq $selected_country ? ' SELECTED' : '';
- $country_html .= "\n<OPTION$selected>$country</OPTION>"
- }
- $country_html .= '</SELECT>';
-
- ($county_html, $state_html, $country_html);
-
-}
-
sub success_default { #html to use if you don't specify a success file
<<'END';
<HTML><HEAD><TITLE>Signup successful</TITLE></HEAD>
diff --git a/httemplate/browse/agent.cgi b/httemplate/browse/agent.cgi
index 2eef5bb91..af3288720 100755
--- a/httemplate/browse/agent.cgi
+++ b/httemplate/browse/agent.cgi
@@ -95,10 +95,30 @@ foreach my $agent ( sort {
<%= $agent->agent %></A></TD>
<TD><A HREF="<%=$p%>edit/agent_type.cgi?<%= $agent->typenum %>"><%= $agent->agent_type->atype %></A></TD>
<TD>
- <FONT COLOR="#00CC00"><B><%= $num_ncancelled %></B></FONT>
- <A HREF="<%= $cust_main_link %>&showcancelledcustomers=0">active</A>
- <BR><FONT COLOR="#FF0000"><B><%= $num_cancelled %></B></FONT>
- <A HREF="<%= $cust_main_link %>&showcancelledcustomers=1&cancelled=1">cancelled</A>
+
+ <B>
+ <%= my $num_prospect = $agent->num_prospect_cust_main %>
+ </B>
+ <% if ( $num_prospect ) { %>
+ <A HREF="<%= $cust_main_link %>&prospect=1"><% } %>prospects<% if ($num_prospect ) { %></A><% } %>
+
+ <BR><FONT COLOR="#00CC00"><B>
+ <%= my $num_active = $agent->num_active_cust_main %>
+ </B></FONT>
+ <% if ( $num_active ) { %>
+ <A HREF="<%= $cust_main_link %>&active=1"><% } %>active<% if ( $num_active ) { %></A><% } %>
+
+ <BR><FONT COLOR="#FF9900"><B>
+ <%= my $num_susp = $agent->num_susp_cust_main %>
+ </B></FONT>
+ <% if ( $num_susp ) { %>
+ <A HREF="<%= $cust_main_link %>&suspended=1"><% } %>suspended<% if ( $num_susp ) { %></A><% } %>
+
+ <BR><FONT COLOR="#FF0000"><B>
+ <%= my $num_cancel = $agent->num_cancel_cust_main %>
+ </B></FONT>
+ <% if ( $num_cancel ) { %>
+ <A HREF="<%= $cust_main_link %>&showcancelledcustomers=1&cancelled=1"><% } %>cancelled<% if ( $num_cancel ) { %></A><% } %>
</TD>
<TD><%= $agent->freq %></TD>
<TD><%= $agent->prog %></TD>
diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi
index 69a78d6fe..632d68df9 100755
--- a/httemplate/search/cust_main.cgi
+++ b/httemplate/search/cust_main.cgi
@@ -82,119 +82,62 @@ if ( $cgi->param('browse')
}
}
- my $ncancelled = '';
+ my @qual = ();
- if ( driver_name eq 'mysql' ) {
-
- my $sql = "CREATE TEMPORARY TABLE temp1_$$ TYPE=MYISAM
- SELECT cust_pkg.custnum,COUNT(*) as count
- FROM cust_pkg,cust_main
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.cancel IS NULL
- OR cust_pkg.cancel = 0 )
- GROUP BY cust_pkg.custnum";
- my $sth = dbh->prepare($sql) or die dbh->errstr. " preparing $sql";
- $sth->execute or die "Error executing \"$sql\": ". $sth->errstr;
- $sql = "CREATE TEMPORARY TABLE temp2_$$ TYPE=MYISAM
- SELECT cust_pkg.custnum,COUNT(*) as count
- FROM cust_pkg,cust_main
- WHERE cust_pkg.custnum = cust_main.custnum
- GROUP BY cust_pkg.custnum";
- $sth = dbh->prepare($sql) or die dbh->errstr. " preparing $sql";
- $sth->execute or die "Error executing \"$sql\": ". $sth->errstr;
- }
+ my $ncancelled = '';
if ( $cgi->param('showcancelledcustomers') eq '0' #see if it was set by me
|| ( $conf->exists('hidecancelledcustomers')
&& ! $cgi->param('showcancelledcustomers') )
) {
#grep { $_->ncancelled_pkgs || ! $_->all_pkgs }
- if ( driver_name eq 'mysql' ) {
- $ncancelled = "
- temp1_$$.custnum = cust_main.custnum
- AND temp2_$$.custnum = cust_main.custnum
- AND (temp1_$$.count > 0
- OR temp2_$$.count = 0 )
- ";
-
- } else {
- $ncancelled = "
- 0 < ( SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.cancel IS NULL
- OR cust_pkg.cancel = 0
- )
- )
- OR 0 = ( SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- )
- ";
- }
- }
-
- my $cancelled = '';
- if ( $cgi->param('cancelled') ) {
- $cancelled = "
- 0 = ( SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.cancel IS NULL
- OR cust_pkg.cancel = 0
- )
- )
- AND 0 < ( SELECT COUNT(*) FROM cust_pkg
+ push @qual, "
+ ( 0 < ( SELECT COUNT(*) FROM cust_pkg
+ WHERE cust_pkg.custnum = cust_main.custnum
+ AND ( cust_pkg.cancel IS NULL
+ OR cust_pkg.cancel = 0
+ )
+ )
+ OR 0 = ( SELECT COUNT(*) FROM cust_pkg
WHERE cust_pkg.custnum = cust_main.custnum
)
+ )
";
- }
+ }
+
+ push @qual, FS::cust_main->cancel_sql if $cgi->param('cancelled');
+ push @qual, FS::cust_main->prospect_sql if $cgi->param('prospect');
+ push @qual, FS::cust_main->active_sql if $cgi->param('active');
+ push @qual, FS::cust_main->susp_sql if $cgi->param('suspended');
#EWWWWWW
my $qual = join(' AND ',
map { "$_ = ". dbh->quote($search{$_}) } keys %search );
- if ( $cancelled ) {
- $qual .= ' AND ' if $qual;
- $qual .= $cancelled;
- } elsif ( $ncancelled ) {
+ my $addl_qual = join(' AND ', @qual);
+
+ if ( $addl_qual ) {
$qual .= ' AND ' if $qual;
- $qual .= $ncancelled;
+ $qual .= $addl_qual;
}
$qual = " WHERE $qual" if $qual;
- my $statement;
- if ( driver_name eq 'mysql' ) {
- $statement = "SELECT COUNT(*) FROM cust_main";
- $statement .= ", temp1_$$, temp2_$$ $qual" if $qual;
- } else {
- $statement = "SELECT COUNT(*) FROM cust_main $qual";
- }
+ my $statement = "SELECT COUNT(*) FROM cust_main $qual";
my $sth = dbh->prepare($statement) or die dbh->errstr." preparing $statement";
$sth->execute or die "Error executing \"$statement\": ". $sth->errstr;
$total = $sth->fetchrow_arrayref->[0];
- my $rqual = $cancelled || $ncancelled;
- if ( $rqual ) {
+ if ( $addl_qual ) {
if ( %search ) {
- $rqual = " AND $rqual";
+ $addl_qual = " AND $addl_qual";
} else {
- $rqual = " WHERE $rqual";
+ $addl_qual = " WHERE $addl_qual";
}
}
- my @just_cust_main;
- if ( driver_name eq 'mysql' ) {
- @just_cust_main = qsearch('cust_main', \%search, 'cust_main.*',
- ",temp1_$$,temp2_$$ $rqual $orderby $limit");
- } else {
- @just_cust_main = qsearch('cust_main', \%search, '',
- "$rqual $orderby $limit" );
- }
- if ( driver_name eq 'mysql' ) {
- my $sql = "DROP TABLE temp1_$$,temp2_$$;";
- my $sth = dbh->prepare($sql) or die dbh->errstr. " preparing $sql";
- $sth->execute or die "Error executing \"$sql\": ". $sth->errstr;
- }
- @cust_main = @just_cust_main;
+ @cust_main = qsearch('cust_main', \%search, '',
+ "$addl_qual $orderby $limit" );
# foreach my $cust_main ( @just_cust_main ) {
#