- bring prepaid support into this century (close: Bug#1124)
authorivan <ivan>
Sat, 12 Mar 2005 14:31:50 +0000 (14:31 +0000)
committerivan <ivan>
Sat, 12 Mar 2005 14:31:50 +0000 (14:31 +0000)
- finally get rid of fs_signup (everything is in fs_selfservice now) (Bug#413)
- organize main menu sysadmin section so it is slightly less confusing

31 files changed:
ANNOUNCE.1.5
FS/FS/agent.pm
FS/FS/cust_main.pm
FS/FS/cust_pay.pm
FS/FS/prepay_credit.pm
FS/bin/freeside-setup
README.1.5.7
fs_selfservice/DEPLOY
fs_selfservice/FS-SelfService/cgi/agent.cgi
fs_selfservice/FS-SelfService/cgi/decline.html [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/map.gif [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/promocode.html [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/regcode.html [new file with mode: 0644]
fs_selfservice/FS-SelfService/cgi/signup-agentselect.html [new file with mode: 0755]
fs_selfservice/FS-SelfService/cgi/signup-alternate.html [new file with mode: 0755]
fs_selfservice/FS-SelfService/cgi/signup-billaddress.html [new file with mode: 0755]
fs_selfservice/FS-SelfService/cgi/signup-freeoption.html [new file with mode: 0755]
fs_selfservice/FS-SelfService/cgi/signup-snarf.html [new file with mode: 0755]
fs_selfservice/FS-SelfService/cgi/signup.cgi [new file with mode: 0755]
fs_selfservice/FS-SelfService/ieak.template [new file with mode: 0755]
httemplate/browse/agent.cgi
httemplate/docs/schema.html
httemplate/docs/selfservice.html
httemplate/docs/upgrade10.html
httemplate/edit/prepay_credit.cgi [new file with mode: 0644]
httemplate/edit/process/prepay_credit.cgi [new file with mode: 0644]
httemplate/edit/process/reg_code.cgi
httemplate/index.html
httemplate/search/elements/search.html
httemplate/search/prepay_credit.html [new file with mode: 0644]
httemplate/view/cust_main/payment_history.html

index 0be1a93..029527f 100644 (file)
@@ -37,6 +37,8 @@
 - package changes don't re-charge setup fee
 - per-agent payment and credit reports
 - CSV and Excel export of most reports, others to be migrated to new report template
+- prepaid card support updated: now includes a web generator, agent-specific
+  prepaid cards, and creates *payments*, not credits
 
 notyet (1.5.8?):
 - account merging UI in exports (for example, to consolidate passwd files from
index 3d8e677..fc1d1a9 100644 (file)
@@ -274,6 +274,7 @@ generated codes, or a scalar error message.
 
 =cut
 
+#false laziness w/prepay_credit::generate
 sub generate_reg_codes {
   my( $self, $num, $pkgparts ) = @_;
 
@@ -325,6 +326,22 @@ sub num_reg_code {
   $sth->fetchrow_arrayref->[0];
 }
 
+=item num_prepay_credit
+
+Returns the number of unused prepaid cards for this agent.
+
+=cut
+
+sub num_prepay_credit {
+  my $self = shift;
+  my $sth = dbh->prepare(
+    "SELECT COUNT(*) FROM prepay_credit WHERE agentnum = ?"
+  ) or die dbh->errstr;
+  $sth->execute($self->agentnum) or die $sth->errstr;
+  $sth->fetchrow_arrayref->[0];
+}
+
+
 =back
 
 =head1 BUGS
index 60556a5..e5748ec 100644 (file)
@@ -175,7 +175,7 @@ FS::Record.  The following fields are currently supported:
 
 =item ship_fax - phone (optional)
 
-=item payby - I<CARD> (credit card - automatic), I<DCRD> (credit card - on-demand), I<CHEK> (electronic check - automatic), I<DCHK> (electronic check - on-demand), I<LECB> (Phone bill billing), I<BILL> (billing), I<COMP> (free), or I<PREPAY> (special billing type: applies a credit - see L<FS::prepay_credit> and sets billing type to I<BILL>)
+=item payby - I<CARD> (credit card - automatic), I<DCRD> (credit card - on-demand), I<CHEK> (electronic check - automatic), I<DCHK> (electronic check - on-demand), I<LECB> (Phone bill billing), I<BILL> (billing), I<COMP> (free), or I<PREPAY> (special billing type: applies a payment from a prepaid card - see L<FS::prepay_credit> - and sets billing type to I<BILL>)
 
 =item payinfo - card number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L<FS::prepay_credit>)
 
@@ -271,20 +271,28 @@ sub insert {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  my $amount = 0;
+  my $prepay_credit = '';
   my $seconds = 0;
   if ( $self->payby eq 'PREPAY' ) {
     $self->payby('BILL');
-    my $prepay_credit = qsearchs(
+    $prepay_credit = qsearchs(
       'prepay_credit',
       { 'identifier' => $self->payinfo },
       '',
       'FOR UPDATE'
     );
-    warn "WARNING: can't find pre-found prepay_credit: ". $self->payinfo
-      unless $prepay_credit;
-    $amount = $prepay_credit->amount;
+    unless ( $prepay_credit ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "Invalid prepaid card: ". $self->payinfo;
+    }
     $seconds = $prepay_credit->seconds;
+    if ( $prepay_credit->agentnum ) {
+      if ( $self->agentnum && $self->agentnum != $prepay_credit->agentnum ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "prepaid card not valid for agent ". $self->agentnum;
+      }
+      $self->agentnum($prepay_credit->agentnum);
+    }
     my $error = $prepay_credit->delete;
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
@@ -321,15 +329,18 @@ sub insert {
     return "No svc_acct record to apply pre-paid time";
   }
 
-  if ( $amount ) {
-    my $cust_credit = new FS::cust_credit {
+  if ( $prepay_credit && $prepay_credit->amount ) {
+    my $cust_pay = new FS::cust_pay {
       'custnum' => $self->custnum,
-      'amount'  => $amount,
+      'paid'    => $prepay_credit->amount,
+      #'_date'   => #date the prepaid card was purchased???
+      'payby'   => 'PREP',
+      'payinfo' => $prepay_credit->identifier,
     };
-    $error = $cust_credit->insert;
+    $error = $cust_pay->insert;
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
-      return "inserting credit (transaction rolled back): $error";
+      return "inserting prepayment (transaction rolled back): $error";
     }
   }
 
index 1ceb599..80d4a14 100644 (file)
@@ -357,7 +357,7 @@ sub check {
 
   $self->_date(time) unless $self->_date;
 
-  $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP)$/ or return "Illegal payby";
+  $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|PREP)$/ or return "Illegal payby";
   $self->payby($1);
 
   #false laziness with cust_refund::check
index a9d26d1..cffedeb 100644 (file)
@@ -2,8 +2,8 @@ package FS::prepay_credit;
 
 use strict;
 use vars qw( @ISA );
-#use FS::Record qw( qsearch qsearchs );
-use FS::Record qw();
+use FS::Record qw(qsearchs dbh);
+use FS::agent;
 
 @ISA = qw(FS::Record);
 
@@ -37,8 +37,8 @@ FS::prepay_credit - Object methods for prepay_credit records
 
 =head1 DESCRIPTION
 
-An FS::table_name object represents an pre--paid credit, such as a pre-paid
-"calling card".  FS::prepay_credit inherits from FS::Record.  The following
+An FS::prepay_credit object represents a pre-paid card.  FS::prepay_credit
+inherits from FS::Record.  The following
 fields are currently supported:
 
 =over 4
@@ -107,14 +107,76 @@ sub check {
   $self->ut_numbern('prepaynum')
   || $self->ut_alpha('identifier')
   || $self->ut_money('amount')
-  || $self->utnumbern('seconds')
+  || $self->ut_numbern('seconds')
+  || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum')
   || $self->SUPER::check
   ;
 
 }
 
+=item agent
+
+Returns the agent (see L<FS::agent>) for this prepaid card, if any.
+
+=cut
+
+sub agent {
+  my $self = shift;
+  qsearchs('agent', { 'agentnum' => $self->agentnum } );
+}
+
 =back
 
+=head1 SUBROUTINES
+
+=over 4
+
+=item generate NUM TYPE HASHREF
+
+Generates the specified number of prepaid cards.  Returns an array reference of
+the newly generated card identifiers, or a scalar error message.
+
+=cut
+
+#false laziness w/agent::generate_reg_codes
+sub generate {
+  my( $num, $type, $hashref ) = @_;
+
+  my @codeset = ();
+  push @codeset, ( 'A'..'Z' ) if $type =~ /alpha/;
+  push @codeset, ( '1'..'9' ) if $type =~ /numeric/;
+
+  local $SIG{HUP} = 'IGNORE';
+  local $SIG{INT} = 'IGNORE';
+  local $SIG{QUIT} = 'IGNORE';
+  local $SIG{TERM} = 'IGNORE';
+  local $SIG{TSTP} = 'IGNORE';
+  local $SIG{PIPE} = 'IGNORE';
+
+  my $oldAutoCommit = $FS::UID::AutoCommit;
+  local $FS::UID::AutoCommit = 0;
+  my $dbh = dbh;
+
+  my @cards = ();
+  for ( 1 ... $num ) {
+    my $prepay_credit = new FS::prepay_credit {
+      'identifier' => join('', map($codeset[int(rand $#codeset)], (0..7) ) ),
+      %$hashref,
+    };
+    my $error = $prepay_credit->check || $prepay_credit->insert;
+    if ( $error ) {
+      $dbh->rollback if $oldAutoCommit;
+      return "(inserting prepay_credit) $error";
+    }
+    push @cards, $prepay_credit->identifier;
+  }
+
+  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+  \@cards;
+
+}
+
 =head1 BUGS
 
 =head1 SEE ALSO
index 5ab6eb9..74aa5e2 100755 (executable)
@@ -890,6 +890,7 @@ sub tables_hash_hack {
         'identifier',  'varchar', '', $char_d,
         'amount',      @money_type,
         'seconds',     'int',     'NULL', '',
+        'agentnum',    'int',     'NULL', '',
       ],
       'primary_key' => 'prepaynum',
       'unique'      => [ ['identifier'] ],
index 7b72dfb..2620d82 100644 (file)
@@ -2,6 +2,7 @@ NOTE: Version numbering has been simplified.  1.5.7 is the version after
 1.5.0pre6.  It is still a development version - releases with odd numbered 
 middle parts (NN in x.NN.x) are development versions, like Perl or Linux.
 
+install DBIx::DBSchema 0.24
 
 CREATE TABLE rate (
     ratenum serial NOT NULL,
@@ -77,6 +78,9 @@ CREATE INDEX h_part_pkg2 ON h_part_pkg ( promo_code );
 ALTER TABLE cust_main ALTER COLUMN zip DROP NOT NULL;
 ALTER TABLE h_cust_main ALTER COLUMN zip DROP NOT NULL;
 
+ALTER TABLE prepay_credit ADD agentnum integer NULL;
+ALTER TABLE h_prepay_credit ADD agentnum integer NULL;
+
 Installs w/integrated RT:
   CREATE SEQUENCE attributes_id_seq;
 
@@ -106,7 +110,7 @@ dbdef-create username
 
 install Javascript::RPC (JavaScript::RPC::Server::CGI), Text::CSV_XS,
 Spreadsheet::WriteExcel, IO-stringy (IO::Scalar) and Frontier::RPC
-((Frontier::RPC2)
+(Frontier::RPC2)
 
 afterwords (for installs w/integrated RT):
 make configure-rt
index 7420df7..6341278 100755 (executable)
@@ -1,20 +1,27 @@
 #!/bin/sh
 
-kill `cat /var/run/freeside-selfservice-server.fs_selfservice.pid`
+#this is a quick hack for my dev machine.  do not use it.
+# see the "make install-selfservice" and "make update-selfservice" makefile
+# targets to properly install this stuff.
 
-( cd ..; make deploy; cd fs_selfservice )
+#kill `cat /var/run/freeside-selfservice-server.fs_selfservice.pid`
 
 cd FS-SelfService
 perl Makefile.PL && make && make install
+cd ..
+
+( cd ..; make deploy; cd fs_selfservice )
 
 cp /home/ivan/freeside/fs_selfservice/FS-SelfService/cgi/* /var/www/MyAccount
-chown freeside /var/www/MyAccount/selfservice.cgi /var/www/MyAccount/agent.cgi
-chmod 755 /var/www/MyAccount/selfservice.cgi /var/www/MyAccount/agent.cgi
+chown freeside /var/www/MyAccount/*.cgi
+chmod 755 /var/www/MyAccount/*.cgi
 ln -s /var/www/MyAccount/selfservice.cgi /var/www/MyAccount/index.cgi || true
 
-cp /home/ivan/freeside/fs_signup/FS-SignupClient/cgi/* /var/www/signup/
-#mv /var/www/signup/signup-snarf.html /var/www/signup/signup.html #!!!!!
-chown freeside /var/www/signup/signup.cgi
-chmod 755 /var/www/signup/signup.cgi
-ln -s /var/www/signup/signup.cgi /var/www/signup/index.cgi || true
+       #cp /home/ivan/freeside/fs_signup/FS-SignupClient/cgi/* /var/www/signup/
+       ##mv /var/www/signup/signup-snarf.html /var/www/signup/signup.html #!!!!!
+       ##mv /var/www/signup/signup-billaddress.html /var/www/signup/signup.html #!!!!!
+       ##mv /var/www/signup/signup-freeoption.html /var/www/signup/signup.html #!!!!!
+       #chown freeside /var/www/signup/signup.cgi
+       #chmod 755 /var/www/signup/signup.cgi
+       #ln -s /var/www/signup/signup.cgi /var/www/signup/index.cgi || true
 
index 92c76f3..695d20e 100644 (file)
@@ -113,7 +113,7 @@ sub process_signup {
 
   my $error = '';
 
-  #some false laziness w/signup.cgi
+  #false laziness w/signup.cgi, identical except for agentnum vs session_id
   my $payby = $cgi->param('payby');
   if ( $payby eq 'CHEK' || $payby eq 'DCHK' ) {
     #$payinfo = join('@', map { $cgi->param( $payby. "_payinfo$_" ) } (1,2) );
@@ -161,17 +161,25 @@ sub process_signup {
   unless ( $error ) {
     my $rv = new_customer ( {
       'session_id'       => $session_id,
-      map { $_ => $cgi->param($_) }
+      map { $_ => scalar($cgi->param($_)) }
         qw( last first ss company
             address1 address2 city county state zip country
             daytime night fax
+
+            ship_last ship_first ship_company
+            ship_address1 ship_address2 ship_city ship_county ship_state
+              ship_zip ship_country
+            ship_daytime ship_night ship_fax
+
             payby payinfo paycvv paydate payname invoicing_list
+            referral_custnum promo_code reg_code
             pkgpart username sec_phrase _password popnum refnum
           ),
         grep { /^snarf_/ } $cgi->param
     } );
     $error = $rv->{'error'};
   }
+  #eslaf
 
   if ( $error ) { 
     $action = 'signup';
@@ -409,7 +417,8 @@ sub do_template {
   #warn join(' / ', map { "$_=>".$fill_in->{$_} } keys %$fill_in). "\n";
 
   $cgi->delete_all();
-  $fill_in->{'selfurl'} = $cgi->self_url;
+  $fill_in->{'selfurl'} = $cgi->self_url; #OLD
+  $fill_in->{'self_url'} = $cgi->self_url;
   $fill_in->{'cgi'} = \$cgi;
 
   my $template = new Text::Template( TYPE    => 'FILE',
diff --git a/fs_selfservice/FS-SelfService/cgi/decline.html b/fs_selfservice/FS-SelfService/cgi/decline.html
new file mode 100644 (file)
index 0000000..a37ba3a
--- /dev/null
@@ -0,0 +1,5 @@
+<HTML><HEAD><TITLE>Processing error</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Processing error</FONT><BR><BR>
+There has been an error processing your account.  Please contact customer
+support.
+</BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/map.gif b/fs_selfservice/FS-SelfService/cgi/map.gif
new file mode 100644 (file)
index 0000000..ef884d8
Binary files /dev/null and b/fs_selfservice/FS-SelfService/cgi/map.gif differ
diff --git a/fs_selfservice/FS-SelfService/cgi/promocode.html b/fs_selfservice/FS-SelfService/cgi/promocode.html
new file mode 100644 (file)
index 0000000..f8ee7f6
--- /dev/null
@@ -0,0 +1,14 @@
+<HTML><HEAD><TITLE>ISP Signup</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>ISP Signup - promotional code</FONT><BR><BR>
+<SCRIPT>
+function gotoURL(object) {
+    window.location.href =  'signup.cgi?promo_code=' + object.promo_code.value;
+}
+</SCRIPT>
+<FORM>
+Enter promotional code <INPUT TYPE="text" NAME="promo_code">
+<INPUT type="submit" VALUE="Signup" onClick="gotoURL(this.form)">
+
+</FORM>
+</BODY>
+</HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/regcode.html b/fs_selfservice/FS-SelfService/cgi/regcode.html
new file mode 100644 (file)
index 0000000..e639b9b
--- /dev/null
@@ -0,0 +1,14 @@
+<HTML><HEAD><TITLE>ISP Signup</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>ISP Signup - registration code</FONT><BR><BR>
+<SCRIPT>
+function gotoURL(object) {
+    window.location.href =  'signup.cgi?reg_code=' + object.reg_code.value;
+}
+</SCRIPT>
+<FORM>
+Enter registration code <INPUT TYPE="text" NAME="reg_code">
+<INPUT type="submit" VALUE="Signup" onClick="gotoURL(this.form)">
+
+</FORM>
+</BODY>
+</HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup-agentselect.html b/fs_selfservice/FS-SelfService/cgi/signup-agentselect.html
new file mode 100755 (executable)
index 0000000..7851c56
--- /dev/null
@@ -0,0 +1,195 @@
+<HTML><HEAD><TITLE>ISP Signup form</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>ISP Signup form</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM NAME="OneTrueForm" ACTION="<%= $self_url %>" METHOD=POST onSubmit="document.OneTrueForm.signup.disabled=true">
+<INPUT TYPE="hidden" NAME="magic" VALUE="process">
+<INPUT TYPE="hidden" NAME="ref" VALUE="<%= $referral_custnum %>">
+<INPUT TYPE="hidden" NAME="ss" VALUE="">
+Agent <SELECT NAME="agentnum">
+<%=
+  warn $init_data;
+  warn $init_data->{'agent'};
+  foreach my $agent ( @{$init_data->{'agent'}} ) {
+    $OUT .= '<OPTION VALUE="'. $agent->{'agentnum'}. '"';
+    $OUT .= ' SELECTED' if $agent->{'agentnum'} eq $agentnum;
+    $OUT .= '>'. $agent->{'agent'};
+  }
+%>
+</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( $county, $state, $country );
+        "$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 = $cgi->param('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>!,
+    );
+
+    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>!,
+    );
+
+    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 $package ( @{$packages} ) {
+      $OUT .= '<OPTION VALUE="'. $package->{'pkgpart'}. '"';
+      $OUT .= ' SELECTED' if $pkgpart && $package->{'pkgpart'} == $pkgpart;
+      $OUT .= '>'. $package->{'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 ( $init_data->{'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 ( scalar(@$pops) ) {
+    $OUT .= '<TR><TD ALIGN="right">Access number</TD><TD>'.
+            popselector($popnum). '</TD></TR>';
+  } else {
+    $OUT .= popselector($popnum);
+  }
+%>
+</TABLE>
+<BR><BR><INPUT TYPE="submit" NAME="signup" VALUE="Signup" >
+</FORM></BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup-alternate.html b/fs_selfservice/FS-SelfService/cgi/signup-alternate.html
new file mode 100755 (executable)
index 0000000..490cefa
--- /dev/null
@@ -0,0 +1,218 @@
+<HTML><HEAD><TITLE>ISP Signup form</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>ISP Signup form</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM NAME="dummy">
+<INPUT TYPE="hidden" NAME="magic" VALUE="process">
+<INPUT TYPE="hidden" NAME="ref" VALUE="<%= $referral_custnum %>">
+<INPUT TYPE="hidden" NAME="ss" VALUE="">
+<INPUT TYPE="hidden" NAME="agentnum" VALUE="3">
+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><SELECT NAME="state" SIZE="1">
+
+  <%=
+    foreach ( @{$locales} ) {
+      my $value = $_->{'state'};
+      $value .= ' ('. $_->{'county'}. ')' if $_->{'county'};
+      $value .= ' / '. $_->{'country'};
+
+      $OUT .= qq(<OPTION VALUE="$value");
+      $OUT .= ' SELECTED' if ( $state eq $_->{'state'}
+                               && $county eq $_->{'county'}
+                               && $country eq $_->{'country'}
+                             );
+      $OUT .= ">$value</OPTION>";
+    }
+  %>
+
+  </SELECT></TD>
+  <TH><font color="#ff0000">*</font>Zip</TH>
+  <TD><INPUT TYPE="text" NAME="zip" SIZE=10 VALUE="<%= $zip %>"></TD>
+</TR>
+<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><BR>
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Username</TH>
+  <TD><INPUT TYPE="text" NAME="username" VALUE="<%= $username %>"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Password</TH>
+  <TD><INPUT TYPE="password" NAME="_password" VALUE="<%= $password %>"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Re-enter Password</TH>
+  <TD><INPUT TYPE="password" NAME="_password2" VALUE="<%= $password2 %>"></TD>
+</TR>
+
+<%= if ( $init_data->{'security_phrase'} ) {
+      <<ENDOUT;
+<TR>
+  <TD ALIGN="right">Security Phrase</TD>
+  <TD><INPUT TYPE="text" NAME="sec_phrase" VALUE="$sec_phrase">
+  </TD>
+</TR>
+ENDOUT
+    } else {
+      '<INPUT TYPE="hidden" NAME="sec_phrase" VALUE="">';
+    }
+%>
+
+<%= if ( scalar(@$pops) ) {
+      '<TR><TD ALIGN="right">Access number</TD><TD>'.
+           popselector($popnum). '</TD></TR>';
+    } else {
+      popselector($popnum);
+    }
+%>
+
+</TABLE><font color="#ff0000">*</font> required fields
+
+<BR><BR>First package
+
+  <%= use Tie::IxHash;
+      my %pkgpart2payby = map { $_->{pkgpart} => $_->{payby}[0] } @{$packages};
+      tie my %options, 'Tie::IxHash',
+        '' => '(none)',
+        map { $_->{pkgpart} => $_->{pkg} }
+          sort { $a->{recur} <=> $b->{recur} }
+            @{$packages} 
+      ;
+
+      use HTML::Widgets::SelectLayers 0.02;
+      my @form_text = qw( magic ref ss agentnum
+                          last first company address1 address2
+                          city zip daytime night fax
+                          username _password _password2 sec_phrase );
+      my @form_select = qw( state ); #county country
+      if ( scalar(@$pops) == 0 or scalar(@$pops) == 1 ) {
+        push @form_text, 'popnum',
+      } else {
+        push @form_select, 'popnum',
+      }
+      my $widget = new HTML::Widgets::SelectLayers(
+        options => \%options,
+        selected_layer => $pkgpart,
+        form_name => 'dummy',
+        form_action => $self_url,
+        form_text => \@form_text,
+        form_select => \@form_select,
+        layer_callback => sub {
+          my $layer = shift;
+          my $html = qq( <INPUT TYPE="hidden" NAME="pkgpart" VALUE="$layer">);
+
+          if ( $pkgpart2payby{$layer} eq 'BILL' ) {
+            $html .= <<ENDOUT;
+<INPUT TYPE="hidden" NAME="payby" VALUE="BILL">
+<INPUT TYPE="hidden" NAME="invoicing_list_POST" VALUE="">
+<INPUT TYPE="hidden" NAME="BILL_payinfo" VALUE="">
+<INPUT TYPE="hidden" NAME="BILL_month" VALUE="12">
+<INPUT TYPE="hidden" NAME="BILL_year" VALUE="2037">
+<INPUT TYPE="hidden" NAME="BILL_payname" VALUE="">
+<BR><BR><INPUT TYPE="submit" VALUE="Signup">
+ENDOUT
+          } elsif ( $pkgpart2payby{$layer} eq 'CARD' ) {
+            my $postal_checked = '';
+            my @invoicing_list = split(', ', $invoicing_list );
+            $postal_checked = 'CHECKED'
+              if ! @invoicing_list || grep { $_ eq 'POST' } @invoicing_list;
+
+            $invoicing_list= join(', ', grep { $_ ne 'POST' } @invoicing_list );
+
+            my $expselect = expselect("CARD", $paydate);
+
+            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 =
+                $cgi->param('CARD_type') eq $types{$_} ? 'SELECTED' : '';
+              $cardselect .=
+                qq!<OPTION $selected VALUE="$types{$_}">$_</OPTION>!;
+            }
+            $cardselect .= '</SELECT>';
+
+            $html .= <<ENDOUT;
+<INPUT TYPE="hidden" NAME="payby" VALUE="CARD">
+<BR><BR>Billing information
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0>
+<INPUT TYPE="hidden" NAME="invoicing_list_POST" VALUE="">
+<TR>
+  <TD ALIGN="right">Email statement to </TD>
+  <TD><INPUT TYPE="text" NAME="invoicing_list" VALUE="$invoicing_list"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Credit card type</TH>
+  <TD>$cardselect</TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Card number</TH>
+  <TD><INPUT TYPE="text" NAME="CARD_payinfo" VALUE="$payinfo" MAXLENGTH=19></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>*</font>Exp</TH>
+  <TD>$expselect</TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Name on card</TH>
+  <TD><INPUT TYPE="text" NAME="CARD_payname" VALUE="$payname"></TD>
+</TR>
+</TABLE>
+<font color="#ff0000">*</font> required fields
+<BR><BR><INPUT TYPE="submit" VALUE="Signup">
+ENDOUT
+          } else {
+            $html = <<ENDOUT;
+<BR>Please select a package.<BR>
+ENDOUT
+
+          }
+
+          $html;
+
+        },
+      );
+
+      $widget->html;
+
+
+ %>
+</BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup-billaddress.html b/fs_selfservice/FS-SelfService/cgi/signup-billaddress.html
new file mode 100755 (executable)
index 0000000..3cf9d25
--- /dev/null
@@ -0,0 +1,307 @@
+<HTML><HEAD><TITLE>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>ISP Signup form</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM NAME="OneTrueForm" ACTION="<%= $self_url %>" METHOD=POST onSubmit="document.OneTrueForm.signup.disabled=true">
+<INPUT TYPE="hidden" NAME="magic" VALUE="process">
+<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 ( @{$init_data->{'part_referral'}} ) {
+    $OUT .= '<OPTION VALUE="'. $part_referral->{'refnum'}. '"';
+    $OUT .= ' SELECTED' if $part_referral->{'refnum'} eq $refnum;
+    $OUT .= '>'. $part_referral->{'referral'};
+  }
+%>
+</SELECT><BR><BR>
+Billing Address (where credit card statement is sent)
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Exact name on card<BR>(last, first)</TH>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="last" VALUE="<%= $last %>" onChange="changed(this)">,
+                <INPUT TYPE="text" NAME="first" VALUE="<%= $first %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Company</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="company" SIZE=70 VALUE="<%= $company %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Address</TH>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="address1" SIZE=70 VALUE="<%= $address1 %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">&nbsp;</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="address2" SIZE=70 VALUE="<%= $address2 %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>City</TH>
+  <TD><INPUT TYPE="text" NAME="city" VALUE="<%= $city %>" onChange="changed(this)"></TD>
+  <TH ALIGN="right"><font color="#ff0000">*</font>State/Country</TH>
+  <TD>
+    <%=
+        ($county_html, $state_html, $country_html) =
+          regionselector( $county, $state, $country, '', 'changed(this)' );
+        "$county_html $state_html";
+    %>
+  </TD>
+  <TH><font color="#ff0000">*</font>Zip</TH>
+  <TD><INPUT TYPE="text" NAME="zip" SIZE=10 VALUE="<%= $zip %>" onChange="changed(this)"></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 onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Night Phone</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="night" VALUE="<%= $night %>" SIZE=18 onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Fax</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="fax" VALUE="<%= $fax %>" SIZE=12 onChange="changed(this)"></TD>
+</TR>
+</TABLE>
+
+<SCRIPT>
+function changed(what) {
+  what.form.same.checked = false;
+}
+function samechanged(what) {
+  if ( what.checked ) {
+
+    <%= foreach (qw(
+          last first company address1 address2 city zip daytime night fax
+        )) {
+          $OUT .= "what.form.ship_$_.value = what.form.$_.value;\n";
+        }
+    %>
+
+    what.form.ship_country.selectedIndex = what.form.country.selectedIndex;
+    ship_country_changed(what.form.ship_country);
+    what.form.ship_state.selectedIndex = what.form.state.selectedIndex;
+    ship_state_changed(what.form.ship_state);
+    what.form.ship_county.selectedIndex = what.form.county.selectedIndex;
+  }
+}
+</SCRIPT>
+
+<BR><BR>
+Service Address
+(<INPUT TYPE="checkbox" NAME="same" VALUE="Y" onClick="samechanged(this)" <%= $same eq 'Y' ? 'CHECKED' : '' %>>same as billing address)<BR>
+<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="ship_last" VALUE="<%= $ship_last %>" onChange="changed(this)">,
+                <INPUT TYPE="text" NAME="ship_first" VALUE="<%= $ship_first %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Company</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="ship_company" SIZE=70 VALUE="<%= $ship_company %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Address</TH>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="ship_address1" SIZE=70 VALUE="<%= $ship_address1 %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">&nbsp;</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="ship_address2" SIZE=70 VALUE="<%= $ship_address2 %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>City</TH>
+  <TD><INPUT TYPE="text" NAME="ship_city" VALUE="<%= $ship_city %>" onChange="changed(this)"></TD>
+  <TH ALIGN="right"><font color="#ff0000">*</font>State/Country</TH>
+  <TD>
+    <%=
+        ($ship_county_html, $ship_state_html, $ship_country_html) =
+          regionselector( $ship_county,
+                          $ship_state,
+                          $ship_country,
+                          'ship_',
+                          'changed(this)',
+                        );
+        "$ship_county_html $ship_state_html";
+    %>
+  </TD>
+  <TH><font color="#ff0000">*</font>Zip</TH>
+  <TD><INPUT TYPE="text" NAME="ship_zip" SIZE=10 VALUE="<%= $ship_zip %>" onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TH ALIGN="right"><font color="#ff0000">*</font>Country</TH>
+  <TD><%= $ship_country_html %></TD>
+<TR>
+  <TD ALIGN="right">Day Phone</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="ship_daytime" VALUE="<%= $ship_daytime %>" SIZE=18 onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Night Phone</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="ship_night" VALUE="<%= $ship_night %>" SIZE=18 onChange="changed(this)"></TD>
+</TR>
+<TR>
+  <TD ALIGN="right">Fax</TD>
+  <TD COLSPAN=5><INPUT TYPE="text" NAME="ship_fax" VALUE="<%= $ship_fax %>" SIZE=12 onChange="changed(this)"></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 = $cgi->param('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 ( $init_data->{'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 ( $init_data->{'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
+<INPUT TYPE="hidden" NAME="promo_code" VALUE="<%= $cgi->param('promo_code') %>">
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR>
+  <TD COLSPAN=2><SELECT NAME="pkgpart">
+
+  <%=
+    $OUT .= '<OPTION VALUE="">(none)' unless scalar(@$packages) == 1;
+    foreach my $package ( @{$packages} ) {
+      $OUT .= '<OPTION VALUE="'. $package->{'pkgpart'}. '"';
+      $OUT .= ' SELECTED'
+        if ( $pkgpart && $package->{'pkgpart'} == $pkgpart )
+           || scalar(@$packages) == 1;
+      $OUT .= '>'. $package->{'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 ( $init_data->{'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 ( scalar(@$pops) ) {
+    $OUT .= '<TR><TD ALIGN="right">Access number</TD><TD>'.
+            popselector($popnum). '</TD></TR>';
+  } else {
+    $OUT .= popselector($popnum);
+  }
+%>
+</TABLE>
+<BR><BR><INPUT TYPE="submit" NAME="signup" VALUE="Signup">
+</FORM></BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup-freeoption.html b/fs_selfservice/FS-SelfService/cgi/signup-freeoption.html
new file mode 100755 (executable)
index 0000000..40ad03c
--- /dev/null
@@ -0,0 +1,262 @@
+<HTML><HEAD><TITLE>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>ISP Signup form</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM NAME="OneTrueForm" ACTION="<%= $self_url %>" METHOD=POST onSubmit="document.OneTrueForm.signup.disabled=true">
+<INPUT TYPE="hidden" NAME="magic" VALUE="process">
+<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 ( @{$init_data->{'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( $county, $state, $country );
+        "$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>
+<%=
+  my $first_payby = $packages->[0]{'payby'}[0];
+  unless ( grep { scalar( @{$_->{'payby'}} ) > 1
+                    || $_->{'payby'}->[0] ne $first_payby
+                } @$packages
+  ) { 
+    @payby = ( $first_payby );
+  }
+
+  unless ( scalar(@payby) == 1 && $payby[0] eq 'BILL' ) {
+
+    $OUT .= ' Billing information
+            <TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+            <TR><TD>
+            <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>';
+
+    $OUT .= '<TR><TD>Billing type</TD></TR>'
+      if scalar(@payby) > 1;
+
+    $OUT .= '</TABLE>';
+
+  } else {
+    $OUT .= '<INPUT TYPE="hidden" NAME="invoicing_list" VALUE="">
+             <INPUT TYPE="hidden" NAME="invoicing_list_POST" VALUE="">';
+  }
+
+%>
+
+<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 = $cgi->param('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' => <<'END',
+<INPUT TYPE="hidden" NAME="BILL_payinfo" VALUE="">
+<INPUT TYPE="hidden" NAME="BILL_month" VALUE="12">
+<INPUT TYPE="hidden" NAME="BILL_year" VALUE="2037">
+<INPUT TYPE="hidden" NAME="BILL_payname" VALUE="">
+END
+      '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 ( $init_data->{'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' => <<'END',
+<INPUT TYPE="hidden" NAME="BILL_payinfo" VALUE="">
+<INPUT TYPE="hidden" NAME="BILL_month" VALUE="12">
+<INPUT TYPE="hidden" NAME="BILL_year" VALUE="2037">
+<INPUT TYPE="hidden" NAME="BILL_payname" VALUE="">
+END
+
+      '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 ( $init_data->{'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>
+<%= unless ( scalar(@payby) == 1 && $payby[0] eq 'BILL' ) {
+      $OUT .= '<font color="#ff0000">*</font> required fields for each billing type';
+    }
+    '';
+%>
+<BR><BR>First package
+<INPUT TYPE="hidden" NAME="promo_code" VALUE="<%= $cgi->param('promo_code') %>"><TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR>
+  <TD COLSPAN=2><SELECT NAME="pkgpart">
+
+  <%=
+    $OUT .= '<OPTION VALUE="">(none)' unless scalar(@$packages) == 1;
+    foreach my $package ( @{$packages} ) {
+      $OUT .= '<OPTION VALUE="'. $package->{'pkgpart'}. '"';
+      $OUT .= ' SELECTED'
+        if ( $pkgpart && $package->{'pkgpart'} == $pkgpart )
+           || scalar(@$packages) == 1;
+      $OUT .= '>'. $package->{'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 ( $init_data->{'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 ( scalar(@$pops) ) {
+    $OUT .= '<TR><TD ALIGN="right">Access number</TD><TD>'.
+            popselector($popnum). '</TD></TR>';
+  } else {
+    $OUT .= popselector($popnum);
+  }
+%>
+</TABLE>
+<BR><BR><INPUT TYPE="submit" NAME="signup" VALUE="Signup">
+</FORM></BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup-snarf.html b/fs_selfservice/FS-SelfService/cgi/signup-snarf.html
new file mode 100755 (executable)
index 0000000..d167efb
--- /dev/null
@@ -0,0 +1,228 @@
+<HTML><HEAD><TITLE>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>ISP Signup form</FONT><BR><BR>
+<FONT SIZE="+1" COLOR="#ff0000"><%= $error %></FONT>
+<FORM ACTION="<%= $self_url %>" METHOD=POST>
+<INPUT TYPE="hidden" NAME="magic" VALUE="process">
+<INPUT TYPE="hidden" NAME="ref" VALUE="<%= $referral_custnum %>">
+<INPUT TYPE="hidden" NAME="ss" VALUE="">
+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( $county, $state, $country );
+        "$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 = $cgi->param('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 ( $init_data->{'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 ( $init_data->{'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 $package ( @{$packages} ) {
+      $OUT .= '<OPTION VALUE="'. $package->{'pkgpart'}. '"';
+      $OUT .= ' SELECTED' if $pkgpart && $package->{'pkgpart'} == $pkgpart;
+      $OUT .= '>'. $package->{'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 ( $init_data->{'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 ( scalar(@$pops) ) {
+    $OUT .= '<TR><TD ALIGN="right">Access number</TD><TD>'.
+            popselector($popnum). '</TD></TR>';
+  } else {
+    $OUT .= popselector($popnum);
+  }
+%>
+</TABLE>
+<BR><BR>Enter up to ten external accounts from which to retrieve email
+<TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
+<TR>
+  <TH ALIGN="left">Mail server</TH>
+  <TH ALIGN="left">Username</TH>
+  <TH ALIGN="left">Password</TH>
+</TR>
+<%=
+  for my $num ( 1..10 ) {
+    no strict 'vars';
+    $OUT .= qq!<TR><TD><INPUT TYPE="text" NAME="snarf_machine$num" VALUE="${"snarf_machine$num"}"></TD>!.
+            qq!<INPUT TYPE="hidden" NAME="snarf_protocol$num" VALUE="pop3">!.
+            qq!<TD><INPUT TYPE="text" NAME="snarf_username$num" VALUE="${"snarf_username$num"}"></TD>!.
+            qq!<TD><INPUT TYPE="password" NAME="snarf_password$num" VALUE="${"snarf_password$num"}"></TD>!.
+            qq!</TR>!;
+  }
+%>
+</TABLE>
+
+<BR><BR><INPUT TYPE="submit" VALUE="Signup">
+</FORM></BODY></HTML>
diff --git a/fs_selfservice/FS-SelfService/cgi/signup.cgi b/fs_selfservice/FS-SelfService/cgi/signup.cgi
new file mode 100755 (executable)
index 0000000..afae1f1
--- /dev/null
@@ -0,0 +1,429 @@
+#!/usr/bin/perl -T
+#!/usr/bin/perl -Tw
+#
+# $Id: signup.cgi,v 1.1 2005-03-12 14:31:50 ivan Exp $
+
+use strict;
+use vars qw( @payby $cgi $init_data
+             $self_url $error $agentnum
+
+             $ieak_file $ieak_template
+             $signup_html $signup_template
+             $success_html $success_template
+             $decline_html $decline_template
+           );
+             #$locales $packages
+             #$pops %pop %popnum2pop
+
+             #$last $first $ss $company $address1
+             #$address2 $city $state $county
+             #$country $zip $daytime $night $fax
+
+             #$ship_last $ship_first $ship_ss $ship_company $ship_address1
+             #$ship_address2 $ship_city $ship_state $ship_county
+             #$ship_country $ship_zip $ship_daytime $ship_night $ship_fax
+
+             #$invoicing_list $payby $payinfo
+             #$paycvv $paydate $payname $referral_custnum $init_popstate
+             #$pkgpart $username $_password $_password2 $sec_phrase $popnum
+             #$refnum
+
+             #$ac $exch $loc
+             #$email_name $pkg
+use subs qw( print_form print_okay print_decline
+             success_default decline_default
+           );
+use CGI;
+#use CGI::Carp qw(fatalsToBrowser);
+use Text::Template;
+use Business::CreditCard;
+use HTTP::BrowserDetect;
+use FS::SelfService qw( signup_info new_customer );
+
+#acceptable payment methods
+#
+#@payby = qw( CARD BILL COMP );
+#@payby = qw( CARD BILL );
+#@payby = qw( CARD );
+@payby = qw( CARD PREPAY );
+
+$ieak_file = '/usr/local/freeside/ieak.template';
+$signup_html = -e 'signup.html'
+                 ? 'signup.html'
+                 : '/usr/local/freeside/signup.html';
+$success_html = -e 'success.html'
+                  ? 'success.html'
+                  : '/usr/local/freeside/success.html';
+$decline_html = -e 'decline.html'
+                  ? 'decline.html'
+                  : '/usr/local/freeside/decline.html';
+
+
+if ( -e $ieak_file ) {
+  my $ieak_txt = Text::Template::_load_text($ieak_file)
+    or die $Text::Template::ERROR;
+  $ieak_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+  $ieak_txt = $1;
+  $ieak_txt =~ s/\r//g; # don't double \r on old templates
+  $ieak_txt =~ s/\n/\r\n/g;
+  $ieak_template = new Text::Template ( TYPE => 'STRING', SOURCE => $ieak_txt )
+    or die $Text::Template::ERROR;
+} else {
+  $ieak_template = '';
+}
+
+$agentnum = '';
+if ( -e $signup_html ) {
+  my $signup_txt = Text::Template::_load_text($signup_html)
+    or die $Text::Template::ERROR;
+  $signup_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+  $signup_txt = $1;
+  $signup_template = new Text::Template ( TYPE => 'STRING',
+                                          SOURCE => $signup_txt,
+                                          DELIMITERS => [ '<%=', '%>' ]
+                                        )
+    or die $Text::Template::ERROR;
+  if ( $signup_txt =~
+         /<\s*INPUT TYPE="?hidden"?\s+NAME="?agentnum"?\s+VALUE="?(\d+)"?\s*>/si
+  ) {
+    $agentnum = $1;
+  }
+} else {
+  #too much maintenance hassle to keep in this file
+  die "can't find ./signup.html or /usr/local/freeside/signup.html";
+  #$signup_template = new Text::Template ( TYPE => 'STRING',
+  #                                        SOURCE => &signup_default,
+  #                                        DELIMITERS => [ '<%=', '%>' ]
+  #                                      )
+  #  or die $Text::Template::ERROR;
+}
+
+if ( -e $success_html ) {
+  my $success_txt = Text::Template::_load_text($success_html)
+    or die $Text::Template::ERROR;
+  $success_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+  $success_txt = $1;
+  $success_template = new Text::Template ( TYPE => 'STRING',
+                                           SOURCE => $success_txt,
+                                           DELIMITERS => [ '<%=', '%>' ],
+                                         )
+    or die $Text::Template::ERROR;
+} else {
+  $success_template = new Text::Template ( TYPE => 'STRING',
+                                           SOURCE => &success_default,
+                                           DELIMITERS => [ '<%=', '%>' ],
+                                         )
+    or die $Text::Template::ERROR;
+}
+
+if ( -e $decline_html ) {
+  my $decline_txt = Text::Template::_load_text($decline_html)
+    or die $Text::Template::ERROR;
+  $decline_txt =~ /^(.*)$/s; #untaint the template source - it's trusted
+  $decline_txt = $1;
+  $decline_template = new Text::Template ( TYPE => 'STRING',
+                                           SOURCE => $decline_txt,
+                                           DELIMITERS => [ '<%=', '%>' ],
+                                         )
+    or die $Text::Template::ERROR;
+} else {
+  $decline_template = new Text::Template ( TYPE => 'STRING',
+                                           SOURCE => &decline_default,
+                                           DELIMITERS => [ '<%=', '%>' ],
+                                         )
+    or die $Text::Template::ERROR;
+}
+
+$cgi = new CGI;
+
+$init_data = signup_info( 'agentnum'   => $agentnum,
+                          'promo_code' => scalar($cgi->param('promo_code')),
+                          'reg_code'   => uc(scalar($cgi->param('reg_code'))),
+                        );
+#$error = $init_data->{'error'};
+#$locales = $init_data->{'cust_main_county'};
+#$packages = $init_data->{'part_pkg'};
+#$pops = $init_data->{'svc_acct_pop'};
+#@payby = @{$init_data->{'payby'}} if @{$init_data->{'payby'}};
+#$packages = $init_data->{agentnum2part_pkg}{$agentnum} if $agentnum;
+
+if (    ( defined($cgi->param('magic')) && $cgi->param('magic') eq 'process' )
+     || ( defined($cgi->param('action')) && $cgi->param('action') eq 'process_signup' )
+   ) {
+
+#    if ( $cgi->param('state') =~ /^(\w*)( \(([\w ]+)\))? ?\/ ?(\w+)$/ ) {
+#      $state = $1;
+#      $county = $3 || '';
+#      $country = $4;
+#    } elsif ( $cgi->param('state') =~ /^(\w*)$/ ) {
+#      $state = $1;
+#      $cgi->param('county') =~ /^([\w ]*)$/
+#        or die "illegal county: ". $cgi->param('county');
+#      $county = $1;
+#      $cgi->param('country') =~ /^(\w+)$/
+#        or die "illegal country: ". $cgi->param('country');
+#      $country = $1;
+#    } else {
+#      die "illegal state: ". $cgi->param('state');
+#    }
+#    if ( $cgi->param('ship_state') =~ /^(\w*)( \(([\w ]+)\))? ?\/ ?(\w+)$/ ) {
+#      $ship_state = $1;
+#      $ship_county = $3 || '';
+#      $ship_country = $4;
+#    } elsif ( $cgi->param('ship_state') =~ /^(\w*)$/ ) {
+#      $ship_state = $1;
+#      $cgi->param('ship_county') =~ /^([\w ]*)$/
+#        or die "illegal county: ". $cgi->param('ship_county');
+#      $ship_county = $1;
+#      #$cgi->param('ship_country') =~ /^(\w+)$/
+#      $cgi->param('ship_country') =~ /^(\w*)$/
+#        or die "illegal ship_country: ". $cgi->param('ship_country');
+#      $ship_country = $1;
+#    #} else {
+#    #  die "illegal ship_state: ". $cgi->param('ship_state');
+#    }
+
+    $error = '';
+
+    $cgi->param('agentnum', $agentnum) if $agentnum;
+    $cgi->param('reg_code', uc(scalar($cgi->param('reg_code'))) );
+
+    #false laziness w/agent.cgi, identical except for agentnum
+    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( {
+        map { $_ => scalar($cgi->param($_)) }
+          qw( last first ss company
+              address1 address2 city county state zip country
+              daytime night fax
+
+              ship_last ship_first ship_company
+              ship_address1 ship_address2 ship_city ship_county ship_state
+                ship_zip ship_country
+              ship_daytime ship_night ship_fax
+
+              payby payinfo paycvv paydate payname invoicing_list
+              referral_custnum promo_code reg_code
+              pkgpart username sec_phrase _password popnum refnum
+              agentnum
+            ),
+          grep { /^snarf_/ } $cgi->param
+      } );
+      $error = $rv->{'error'};
+    }
+    #eslaf
+    
+    if ( $error eq '_decline' ) {
+      print_decline();
+    } elsif ( $error ) {
+      #fudge the snarf info
+      no strict 'refs';
+      ${$_} = $cgi->param($_) foreach grep { /^snarf_/ } $cgi->param;
+      print_form();
+    } else {
+      print_okay(
+        'pkgpart' => scalar($cgi->param('pkgpart')),
+      );
+    }
+
+} else {
+  $error = '';
+#  $last = '';
+#  $first = '';
+#  $ss = '';
+#  $company = '';
+#  $address1 = '';
+#  $address2 = '';
+#  $city = '';
+#  $state = $init_data->{statedefault};
+#  $county = '';
+#  $country = $init_data->{countrydefault};
+#  $zip = '';
+#  $daytime = '';
+#  $night = '';
+#  $fax = '';
+#  $ship_last = '';
+#  $ship_first = '';
+#  $ship_company = '';
+#  $ship_address1 = '';
+#  $ship_address2 = '';
+#  $ship_city = '';
+#  $ship_state = $init_data->{statedefault};
+#  $ship_county = '';
+#  $ship_country = $init_data->{countrydefault};
+#  $ship_zip = '';
+#  $ship_daytime = '';
+#  $ship_night = '';
+#  $ship_fax = '';
+#  $invoicing_list = '';
+#  $payby = '';
+#  $payinfo = '';
+#  $paydate = '';
+#  $payname = '';
+#  $pkgpart = '';
+#  $username = '';
+#  $_password = '';
+#  $_password2 = '';
+#  $sec_phrase = '';
+#  $popnum = '';
+#  $referral_custnum = $cgi->param('ref') || '';
+#  $init_popstate = $cgi->param('init_popstate') || '';
+#  $refnum = $init_data->{'refnum'};
+  print_form;
+}
+
+sub print_form {
+
+  $error = "Error: $error" if $error;
+
+  my $r = {
+    $cgi->Vars,
+    %{$init_data},
+    'error' => $error,
+  };
+
+  $r->{referral_custnum} = $r->{'ref'};
+  #$cgi->delete('ref');
+  #$cgi->delete('init_popstate');
+  $r->{self_url} = $cgi->self_url;
+
+  print $cgi->header( '-expires' => 'now' ),
+        $signup_template->fill_in( PACKAGE => 'FS::SelfService::_signupcgi',
+                                   HASH    => $r
+                                 );
+}
+
+sub print_decline {
+  print $cgi->header( '-expires' => 'now' ),
+        $decline_template->fill_in();
+}
+
+sub print_okay {
+  my %param = @_;
+  my $user_agent = new HTTP::BrowserDetect $ENV{HTTP_USER_AGENT};
+
+  $cgi->param('username') =~ /^(.+)$/
+    or die "fatal: invalid username got past FS::SelfService::new_customer";
+  my $username = $1;
+  $cgi->param('_password') =~ /^(.+)$/
+    or die "fatal: invalid password got past FS::SelfService::new_customer";
+  my $password = $1;
+  ( $cgi->param('first'). ' '. $cgi->param('last') ) =~ /^(.*)$/
+    or die "fatal: invalid email_name got past FS::SelfService::new_customer";
+  my $email_name = $1; #global for template
+
+  #my %pop = ();
+  my %popnum2pop = ();
+  foreach ( @{ $init_data->{'svc_acct_pop'} } ) {
+    #push @{ $pop{ $_->{state} }->{ $_->{ac} } }, $_;
+    $popnum2pop{$_->{popnum}} = $_;
+  }
+
+  my( $ac, $exch, $loc);
+  my $pop = $popnum2pop{$cgi->param('popnum')};
+    #or die "fatal: invalid popnum got past FS::SelfService::new_customer";
+  if ( $pop ) {
+    ( $ac, $exch, $loc ) = ( $pop->{'ac'}, $pop->{'exch'}, $pop->{'loc'} );
+  } else {
+    ( $ac, $exch, $loc ) = ( '', '', ''); #presumably you're not using them.
+  }
+
+  #global for template
+  my $pkg = ( grep { $_->{'pkgpart'} eq $param{'pkgpart'} }
+                   @{ $init_data->{'part_pkg'} }
+            )[0]->{'pkg'};
+
+  if ( $ieak_template && $user_agent->windows && $user_agent->ie ) {
+    #send an IEAK config
+    print $cgi->header('application/x-Internet-signup'),
+          $ieak_template->fill_in();
+  } else { #send a simple confirmation
+    print $cgi->header( '-expires' => 'now' ),
+          $success_template->fill_in( HASH => {
+            username   => $username,
+            password   => $password,
+            _password  => $password,
+            email_name => $email_name,
+            ac         => $ac,
+            exch       => $exch,
+            loc        => $loc,
+            pkg        => $pkg,
+          });
+  }
+}
+
+sub success_default { #html to use if you don't specify a success file
+  <<'END';
+<HTML><HEAD><TITLE>Signup successful</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Signup successful</FONT><BR><BR>
+Thanks for signing up!
+<BR><BR>
+Signup information for <%= $email_name %>:
+<BR><BR>
+Username: <%= $username %><BR>
+Password: <%= $password %><BR>
+Access number: (<%= $ac %>) / <%= $exch %> - <%= $local %><BR>
+Package: <%= $pkg %><BR>
+</BODY></HTML>
+END
+}
+
+sub decline_default { #html to use if there is a decline
+  <<'END';
+<HTML><HEAD><TITLE>Processing error</TITLE></HEAD>
+<BODY BGCOLOR="#e8e8e8"><FONT SIZE=7>Processing error</FONT><BR><BR>
+There has been an error processing your account.  Please contact customer
+support.
+</BODY></HTML>
+END
+}
+
+# subs for the templates...
+
+package FS::SelfService::_signupcgi;
+use HTML::Entities;
+use FS::SelfService qw(regionselector expselect popselector);
+
diff --git a/fs_selfservice/FS-SelfService/ieak.template b/fs_selfservice/FS-SelfService/ieak.template
new file mode 100755 (executable)
index 0000000..52edaa9
--- /dev/null
@@ -0,0 +1,40 @@
+[Entry]
+Entry_Name = The Internet
+[Phone]
+Dial_As_Is=no
+Phone_Number = { $exch. $loc }
+Area_Code = { $ac }
+Country_Code = 1
+Country_Id = 1
+[Server]
+Type = PPP
+SW_Compress = Yes
+PW_Encrypt = Yes
+Negotiate_TCP/IP = Yes
+Disable_LCP = No
+[TCP/IP]
+Specify_IP_Address = No
+Specity_Server_Address = No
+IP_Header_Compress = Yes
+Gateway_On_Remote = Yes
+[User]
+Name = { $username }
+Password = { $password }
+Display_Password = Yes
+[Internet_Mail]
+Email_Name = { $email_name }
+Email_Address = { $username }\@domain.tld
+POP_Server = mail.domain.tld
+POP_Server_Port_Number = 110
+POP_Login_Name = { $username }
+POP_Login_Password = { $password }
+SMTP_Server = mail.domain.tld
+SMTP_Server_Port_Number = 25
+Install_Mail = 1
+[Internet_News]
+NNTP_Server = news.domain.tld
+NNTP_Server_Port_Number = 119
+Logon_Required = No
+Install_News = 1
+[Branding]
+Window_Title = The Internet
index 82f18bf..d8c74d1 100755 (executable)
@@ -37,6 +37,7 @@ full offerings (via their type).<BR><BR>
   <TH>Customers</TH>
   <TH>Reports</TH>
   <TH>Registration Codes</TH>
+  <TH>Prepaid cards</TH>
   <TH><FONT SIZE=-1>Freq.</FONT></TH>
   <TH><FONT SIZE=-1>Prog.</FONT></TH>
 </TR>
@@ -106,6 +107,13 @@ foreach my $agent ( sort {
           <BR><A HREF="<%=$p%>edit/reg_code.cgi?agentnum=<%= $agent->agentnum %>">Generate codes</A>
         </TD>
 
+        <TD>
+          <%= my $num_prepay_credit = $agent->num_prepay_credit %>
+          <% if ( $num_prepay_credit ) { %>
+            <A HREF="<%=$p%>search/prepay_credit.html?agentnum=<%= $agent->agentnum %>"><% } %>Unused<% if ( $num_prepay_credit ) { %></A><% } %>
+          <BR><A HREF="<%=$p%>edit/prepay_credit.cgi?agentnum=<%= $agent->agentnum %>">Generate cards</A>
+        </TD>
+
         <TD><%= $agent->freq %></TD>
         <TD><%= $agent->prog %></TD>
 
index 63c7953..e968875 100644 (file)
         <li>nasport - port number on the NAS
         <li>nasnum - <a href="#nas">NAS</a>
       </ul>
-    <li><a name="prepay_credit" href="man/FS/prepay_credit.html">prepay_credit</a>
+    <li><a name="prepay_credit" href="man/FS/prepay_credit.html">prepay_credit</a> - prepaid cards
       <ul>
         <li>prepaynum - primary key
-        <li>identifier - text or numeric string used to receive this credit
-        <li>amount - amount of credit
+        <li>identifier - text or numeric string of prepaid card
+        <li>amount - amount of prepayment
+        <li>seconds - prepaid time instead of (or in addition to) monetary value
+        <li>agentnum - optional agent assignment for prepaid cards
       </ul>
     <li><a name="session" href="man/FS/session.html">session</a>
       <ul>
index e533ed2..6d17ead 100644 (file)
@@ -16,19 +16,26 @@ machine, not the backend Freeside server.  On the public machine, install:
   <li><a href="http://search.cpan.org/search?dist=HTTP-BrowserDetect">HTTP::BrowserDetect</a>
 
   <li><a href="man/FS/SelfService.html">FS::SelfService</a> (copy the fs_selfservice/FS-SelfService directory to the external machine, then: perl Makefile.PL; make; make install)
-  <li><a href="man/FS/SignupClient.html">FS::SignupClient</a> (copy the fs_signup/FS-SignupClient directory to the external machine, then: perl Makefile.PL; make; make install)
 </ul>
 Then:
 <ul>
   <li>Set the <a href="../config/config.cgi#unclassified"><i>signup_server-default_agentnum</i></a> configuration value to a default <a href="../browse/agent.cgi">agent number</a>.
   <li>Set the <a href="../config/config.cgi#unclassified"><i>signup_server-default_refnum</i></a> to a default <a href="../browse/part_referral.cgi">advertising source</a>.
   <li>Add the user `freeside' to the the external machine.
-  <li>Copy or symlink the <pre>fs_selfservice/FS-SelfService/cgi/</pre> directory into the web server's document space, for customer self-service and reseller access.  Optionally, customize the .html templates.
-  <li>Copy or symlink the <pre>fs_signup/FS-SignupClient/cgi/</pre> directory into the web server's document space, for signups. Optionally, customize the .html templates.
+  <li>Copy or symlink the <code>fs_selfservice/FS-SelfService/cgi/</code> directory into the web server's document space.  Optionally, customize the .html templates.  "Entry points" (useful places to link to) are:
+    <ul>
+      <li>signup.cgi - Signup
+      <li>selfservice.cgi - Customer self-service
+      <li>agent.cgi - Reseller interface
+      <li>passwd.cgi - Simple password-changing interface
+      <li>promocode.html - Promotional code pre-signup
+      <li>regcode.html - Registration code pre-signup
+      <li>stateselect.html - State selection pre-signup
+    </ul>
   <li>When linking to signup.cgi, you can include a referring custnum in the URL as follows: <code>http://public.web.server/path/signup.cgi?ref=1542</code>
   <li>Enable CGI execution for files with the `.cgi' extension.  (with <a href="http://www.apache.org/docs/mod/mod_mime.html#addhandler">Apache</a>)
   <li>Create the /usr/local/freeside directory on the external machine (owned by the freeside user).
-  <li>touch /usr/local/freeside/fs_signupd_socket; chown freeside /usr/local/freeside/fs_signupd_socket; chmod 600 /usr/local/freeside/fs_signupd_socket
+  <li>touch /usr/local/freeside/selfservice_socket; chown freeside /usr/local/freeside/selfservice_socket; chmod 600 /usr/local/freeside/selfservice_socket
   <li>Use <a href="http://www.apache.org/docs/suexec.html">suEXEC</a> or <a href="http://www.perl.com/CPAN-local/doc/manual/html/pod/perlsec.html#Security_Bugs">setuid</a> (see <a href="install.html">install.html</a> for details) to run signup.cgi, selfservice.cgi, agent.cgi and passwd.cgi as the freeside user.
   <li>Append the identity.pub from the freeside user on your freeside machine to the authorized_keys file of the newly created freeside user on the external machine(s).
   <li>Run an instance of <pre>freeside-selfservice-server <i>user</i> <i>machine</i> <i>agentnum</i> <i>refnum</i></pre> on the Freeside machine for each external machine.
@@ -42,7 +49,7 @@ Then:
 Optional:
 <ul>
   <li>If you create a <b>/usr/local/freeside/ieak.template</b> file on the external machine, it will be sent to IE users with MIME type <i>application/x-Internet-signup</i>.  This file will be processed with <a href="http://search.cpan.org/doc/MJD/Text-Template-1.23/Template.pm">Text::Template</a> with the variables listed below available.
-  (an example file is included as <b>fs_signup/ieak.template</b>)  See the section on <a href="http://www.microsoft.com/windows/ieak/techinfo/deploy/60/en/INS.HTM">internet settings files</a> in the <a href="http://www.microsoft.com/windows/ieak/techinfo/deploy/60/en/toc.asp">IEAK documentation</a> for more information.
+  (an example file is included as <b>fs_selfservice/FS-SelfService/ieak.template</b>)  See the section on <a href="http://www.microsoft.com/windows/ieak/techinfo/deploy/60/en/INS.HTM">internet settings files</a> in the <a href="http://www.microsoft.com/windows/ieak/techinfo/deploy/60/en/toc.asp">IEAK documentation</a> for more information.
 <!--  <li>If you create a <b>/usr/local/freeside/success.html</b> file on the external machine, it will be used as the success HTML page.  Although template substiutions are available, a regular HTML file will work fine here, unlike signup.html.  An example file is included as <b>fs_signup/FS-SignupClient/cgi/success.html</b>-->
   <li>Variable substitutions available in <b>ieak.template</b> and <b>success.html</b>:
     <ul>
index 2a60ca4..76c4933 100644 (file)
@@ -2,7 +2,7 @@
 this is incomplete
 
 install DBD::Pg 1.32 (or, if you're using a Perl version before 5.6, you could try installing DBD::Pg 1.22 with <a href="http://420.am/~ivan/DBD-Pg-1.22-fixvercmp.patch">this patch</a> and commenting out the "use DBD::Pg 1.32" at the top of DBIx/DBSchema/DBD/Pg.pm)
-install DBIx::DBSchema 0.23
+install DBIx::DBSchema 0.24
 install Net::SSH 0.08
 - If using Apache::ASP, add PerlSetVar RequestBinaryRead Off and PerlSetVar IncludesDir /your/freeside/document/root/ to your Apache configuration and make sure you are using Apache::ASP minimum version 2.55.
 - In httpd.conf, change &lt;Files ~ \.cgi&gt; to  &lt;Files ~ (\.cgi|\.html)&gt;
@@ -291,6 +291,8 @@ ALTER TABLE part_pkg ADD promo_code varchar(80) NULL;
 ALTER TABLE h_part_pkg ADD promo_code varchar(80) NULL;
 CREATE INDEX part_pkg2 ON part_pkg ( promo_code );
 CREATE INDEX h_part_pkg2 ON h_part_pkg ( promo_code );
+ALTER TABLE prepay_credit ADD agentnum integer NULL;
+ALTER TABLE h_prepay_credit ADD agentnum integer NULL;
 
 On recent Pg versions:
 
diff --git a/httemplate/edit/prepay_credit.cgi b/httemplate/edit/prepay_credit.cgi
new file mode 100644 (file)
index 0000000..9cf0fc6
--- /dev/null
@@ -0,0 +1,56 @@
+<%
+my $agent = '';
+my $agentnum = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+  $agent = qsearchs('agent', { 'agentnum' => $agentnum=$1 } );
+}
+
+tie my %multiplier, 'Tie::IxHash',
+  1    => 'seconds',
+  60   => 'minutes',
+  3600 => 'hours',
+;
+
+$cgi->param('multiplier', '60') unless $cgi->param('multiplier');
+
+%>
+
+<%= header('Generate prepaid cards'. ($agent ? ' for '. $agent->agent : ''),
+           menubar( 'Main Menu' => $p, ))
+%>
+
+<% if ( $cgi->param('error') ) { %>
+  <FONT SIZE="+1" COLOR="#FF0000">Error: <%= $cgi->param('error') %></FONT>
+<% } %>
+
+<FORM ACTION="<%=popurl(1)%>process/prepay_credit.cgi" METHOD="POST" NAME="OneTrueForm" onSubmit="document.OneTrueForm.submit.disabled=true">
+
+Generate
+<INPUT TYPE="text" NAME="num" VALUE="<%= $cgi->param('num') || '(quantity)' %>" SIZE=10 MAXLENGTH=10 onFocus="if ( this.value == '(quantity)' ) { this.value = ''; }">
+<SELECT NAME="type">
+<% foreach (qw(alpha alphanumeric numeric)) { %>
+  <OPTION<%= $cgi->param('type') eq $_ ? ' SELECTED' : '' %>><%= $_ %>
+<% } %>
+</SELECT>
+ prepaid cards
+
+<BR>for <SELECT NAME="agentnum"><OPTION>(any agent)
+<% foreach my $opt_agent ( qsearch('agent', { 'disabled' => '' } ) ) { %>
+  <OPTION VALUE="<%= $opt_agent->agentnum %>"<%= $opt_agent->agentnum == $agentnum ? ' SELECTED' : '' %>><%= $opt_agent->agent %>
+<% } %>
+</SELECT>
+
+<BR>Value: 
+$<INPUT TYPE="text" NAME="amount" SIZE=8 MAXLENGTH=7 VALUE="<%= $cgi->param('amount') %>">
+and/or
+<INPUT TYPE="text" NAME="seconds" SIZE=6 MAXLENGTH=5 VALUE="<%= $cgi->param('seconds') %>">
+<SELECT NAME="multiplier">
+<% foreach my $multiplier ( keys %multiplier ) { %>
+  <OPTION VALUE="<%= $multiplier %>"<%= $cgi->param('multiplier') eq $multiplier ? ' SELECTED' : '' %>><%= $multiplier{$multiplier} %>
+<% } %>
+</SELECT>
+<BR><BR>
+<INPUT TYPE="submit" NAME="submit" VALUE="Generate" onSubmit="this.disabled = true">
+
+</FORM></BODY></HTML>
+
diff --git a/httemplate/edit/process/prepay_credit.cgi b/httemplate/edit/process/prepay_credit.cgi
new file mode 100644 (file)
index 0000000..25ecbe0
--- /dev/null
@@ -0,0 +1,51 @@
+<%
+my $hashref = {};
+
+my $agent = '';
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+  $agent = qsearchs('agent', { 'agentnum' => $hashref->{agentnum}=$1 } );
+}
+
+my $error = '';
+
+my $num = 0;
+if ( $cgi->param('num') =~ /^\s*(\d+)\s*$/ ) {
+  $num = $1;
+} else {
+  $error = 'Illegal number of prepaid cards: '. $cgi->param('num');
+}
+
+$hashref->{amount} = $cgi->param('amount');
+$hashref->{seconds} = $cgi->param('seconds') * $cgi->param('multiplier');
+
+$error ||= FS::prepay_credit::generate( $num,
+                                        scalar($cgi->param('type')), 
+                                        $hashref
+                                      );
+
+unless ( ref($error) ) {
+  $cgi->param('error', $error );
+%><%=
+  $cgi->redirect(popurl(3). "edit/prepay_credit.cgi?". $cgi->query_string )
+%><% } else { %>
+
+<%= header( "$num prepaid cards generated".
+              ( $agent ? ' for '.$agent->agent : '' ),
+            menubar( 'Main menu' => popurl(3) )
+          )
+%>
+
+<FONT SIZE="+1">
+<% foreach my $card ( @$error ) { %>
+  <code><%= $card %></code>
+  -
+  <%= $hashref->{amount} ? sprintf('$%.2f', $hashref->{amount} ) : '' %>
+  <%= $hashref->{amount} && $hashref->{seconds} ? 'and' : '' %>
+  <%= $hashref->{seconds} ? duration_exact($hashref->{seconds}) : '' %>
+  <br>
+<% } %>
+
+</FONT>
+
+</BODY></HTML>
+<% } %>
index 581ede8..4658257 100644 (file)
@@ -22,11 +22,14 @@ my @pkgparts =
 
 $error ||= $agent->generate_reg_codes($num, \@pkgparts);
 
-unless ( ref($error) ) { %><%=
+unless ( ref($error) ) {
+  $cgi->param('error'. $error );
+%><%=
   $cgi->redirect(popurl(3). "edit/reg_code.cgi?". $cgi->query_string )
 %><% } else { %>
 
 <%= header("$num registration codes generated for ". $agent->agent, menubar(
+  'Main menu'       => popurl(3),
   'View all agents' => popurl(3). 'browse/agent.cgi',
 ) ) %>
 
index b3b1c23..c267602 100644 (file)
       <BR><BR><A HREF="search/report_prepaid_income.html">Prepaid Income (Unearned Revenue) Report</A>
       <BR><BR><A HREF="search/report_tax.html">Sales Tax Liability Report</A>
       <BR><BR>
-      <CENTER><HR WIDTH="94%" NOSHADE></CENTER><BR>
-      <A NAME="admin">Administration</a>
-        <ul>
-          <LI><A HREF="browse/part_pkg.cgi">View/Edit package definitions</A>
-            - One or more services are grouped together into a package and
-              given pricing information.  Customers purchase packages, not
-              services.
-<!--          <LI><A HREF="browse/agent_type.cgi">View/Edit agent types</A>
-            - Agent types define groups of package definitions that you can
-              then assign to particular agents.
-          <LI><A HREF="browse/agent.cgi">View/Edit agents</A>
-            - Agents are resellers of your service.  Agents may be limited
-              to a subset of your full offerings (via their type).
--->
-          <LI><A HREF="browse/cust_main_county.cgi">View/Edit locales and tax rates</A>
-            - Change tax rates, or break down a country into states, or a state
-              into counties and assign different tax rates to each.
-          <LI><A HREF="browse/part_bill_event.cgi">View/Edit invoice events</A> - Actions for overdue invoices
-        </ul>
-      <BR>
     </TD></TR>
     </TABLE>
 
       <BR><A HREF="misc/dump.cgi">Download database dump</A>
       <BR><BR><CENTER><HR WIDTH="94%" NOSHADE></CENTER><BR>
       <A NAME="config" HREF="config/config-view.cgi">Configuration</a><!-- - <font size="+2" color="#ff0000">start here</font> -->
-      <BR><BR><A NAME="admin">Administration</a>
+      <BR><BR><A NAME="admin">Provisioning, services and packages</a>
         <ul>
           <LI><A HREF="browse/part_export.cgi">View/Edit exports</A>
             - Provisioning services to external machines, databases and APIs.
             - One or more services are grouped together into a package and
               given pricing information.  Customers purchase packages, not
               services.
+        </ul>
+      <A NAME="admin_agent">Resellers</a>
+        <ul>
           <LI><A HREF="browse/agent_type.cgi">View/Edit agent types</A>
             - Agent types define groups of package definitions that you can
               then assign to particular agents.
           <LI><A HREF="browse/agent.cgi">View/Edit agents</A>
             - Agents are resellers of your service.  Agents may be limited
               to a subset of your full offerings (via their type).
-          <LI><A HREF="browse/part_referral.cgi">View/Edit advertising sources</A>
-            - Where a customer heard about your service.  Tracked for
-              informational purposes.
+        </ul>
+      <A NAME="admin_billing">Billing</a>
+        <ul>
+          <LI><A HREF="browse/part_bill_event.cgi">View/Edit invoice events</A>
+            - Actions for overdue invoices
+          <LI><A HREF="search/prepay_credit.html">View/Edit prepaid cards</A>
+            - View outstanding cards, generate new cards
+         <LI><A HREF="browse/rate.cgi">View/Edit call rates and regions</A>
+           - Manage rate plans, regions and prefixes for VoIP and call billing.
           <LI><A HREF="browse/cust_main_county.cgi">View/Edit locales and tax rates</A>
             - Change tax rates, or break down a country into states, or a state
               into counties and assign different tax rates to each.
+        </ul>
+      <A NAME="admin_svc_acct">Dialup</a>
+        <ul>
           <LI><A HREF="browse/svc_acct_pop.cgi">View/Edit access numbers</A>
             - Points of Presence 
-          <LI><A HREF="browse/part_bill_event.cgi">View/Edit invoice events</A> - Actions for overdue invoices
-         <LI><A HREF="browse/msgcat.cgi">View/Edit message catalog</A> - Change error messages and other customizable labels.
-    <LI><A HREF="browse/part_virtual_field.cgi">View/Edit virtual fields</A>
-         - Locally defined fields
+        </ul>
+      <A NAME="admin_svc_broadband">Fixed (username-less) broadband</a>
+        <ul>
          <LI><A HREF="browse/router.cgi">View/Edit routers</A>
          - Broadband access routers
          <LI><A HREF="browse/addr_block.cgi">View/Edit address blocks</A>
          - Manage address blocks and block assignments to broadband routers.
-         <LI><A HREF="browse/rate.cgi">View/Edit call rates and regions</A>
-         - Manage rate plans, regions and prefixes for VoIP and call billing.
+       </ul>
+      <A NAME="admin_misc">Miscellaneous</a>
+        <ul>
+          <LI><A HREF="browse/part_referral.cgi">View/Edit advertising sources</A>
+            - Where a customer heard about your service.  Tracked for
+              informational purposes.
+          <LI><A HREF="browse/part_virtual_field.cgi">View/Edit virtual fields</A>
+         - Locally defined fields
+         <LI><A HREF="browse/msgcat.cgi">View/Edit message catalog</A>
+         - Change error messages and other customizable labels.
        </ul>
         <BR>
       </TD></TR>
index 6bd6b03..53aa309 100644 (file)
     } else {
       ( my $xlsname = $opt{'name'} ) =~ s/\W//g;
       $opt{'name'} =~ s/s$// if $total == 1;
+
+      my @menubar = ();
+      if ( $opt{'menubar'} ) {
+        @menubar = @{ $opt{'menubar'} };
+      } else {
+        @menubar = ( 'Main menu' => $p );
+      }
   %>
   <%= include( '/elements/header.html', $opt{'title'},
-                 include( '/elements/menubar.html', 'Main menu' => $p )
+                 include( '/elements/menubar.html', @menubar )
              )
   %>
   <% my $pager = include ( '/elements/pager.html',
   
     <TABLE>
       <TR>
-        <TD>
+        <TD VALIGN="bottom">
           <%= $total %> total <%= $opt{'name'} %><BR>
           <% if ( $opt{'count_addl'} ) { %>
             <% my $n=0; foreach my $count ( @{$opt{'count_addl'}} ) { %>
diff --git a/httemplate/search/prepay_credit.html b/httemplate/search/prepay_credit.html
new file mode 100644 (file)
index 0000000..8c8f57b
--- /dev/null
@@ -0,0 +1,43 @@
+<%
+my $agent = '';
+my $hashref = {};
+if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
+  $hashref->{agentnum} = $1;
+  $agent = qsearchs('agent', { 'agentnum' => $1 } );
+}
+
+my $count_query = 'SELECT COUNT(*) FROM prepay_credit';
+$count_query .= ' WHERE agentnum = '. $agent->agentnum if $agent;
+
+%><%= include( 'elements/search.html',
+                 'title'       => 'Unused Prepaid Cards'.
+                                  ($agent ? ' for '. $agent->agent : ''),
+                 'menubar'     => [
+                   'Main menu'      => $p,
+                   'Generate cards' => $p.'edit/prepay_credit.cgi',
+                 ],
+                 'name'        => 'prepaid cards',
+                 'query'       => {  'table'   => 'prepay_credit',
+                                     'hashref' => $hashref,
+                                  },
+                 'count_query' => $count_query,
+                 #'redirect'    => $link,
+                 'header'      => [ '#', qw(Amount Time Agent) ],
+                 'fields'      => [
+                   'identifier',
+                   sub { sprintf('$%.2f', shift->amount ) },
+                   sub { my $c = shift; $c ? duration_exact($c->seconds) : '' },
+                   sub { my $agent = shift->agent;
+                         $agent ? $agent->agent : '';
+                       },
+                 ],
+                 'links' => [
+                   '',
+                   '',
+                   '',
+                   sub { my $agent = shift->agent;
+                         $agent ? [ "${p}view/agent.cgi?", 'agentnum' ] : '';
+                       },
+                 ],
+      )
+%>
index 0f3a987..db01ebb 100644 (file)
@@ -50,6 +50,7 @@ foreach my $cust_pay ($cust_main->cust_pay) {
   my $target = "$payby$payinfo";
   $payby =~ s/^BILL$/Check #/ if $payinfo;
   $payby =~ s/^CHEK$/Electronic check /;
+  $payby =~ s/^PREP$/Prepaid card /;
   $payby =~ s/^BILL$//;
   $payby =~ s/^(CARD|COMP)$/$1 /;
   my $info = $payby ? " ($payby$payinfo)" : '';