promo codes and separate signup addresses for hdn
authorivan <ivan>
Mon, 22 Nov 2004 18:20:21 +0000 (18:20 +0000)
committerivan <ivan>
Mon, 22 Nov 2004 18:20:21 +0000 (18:20 +0000)
15 files changed:
FS/FS/ClientAPI/Signup.pm
FS/FS/Record.pm
FS/FS/cust_pkg.pm
FS/FS/part_pkg.pm
FS/bin/freeside-setup
README.1.5.0pre7
fs_signup/FS-SignupClient/SignupClient.pm
fs_signup/FS-SignupClient/cgi/promocode.html [new file with mode: 0644]
fs_signup/FS-SignupClient/cgi/signup-billaddress.html [new file with mode: 0755]
fs_signup/FS-SignupClient/cgi/signup.cgi
fs_signup/FS-SignupClient/cgi/signup.html
httemplate/docs/schema.html
httemplate/docs/upgrade10.html
httemplate/edit/cust_main.cgi
httemplate/edit/part_pkg.cgi

index bdcd2fb..dc627e9 100644 (file)
@@ -75,6 +75,8 @@ sub signup_info {
 
     'cvv_enabled' => defined dbdef->table('cust_main')->column('paycvv'),
 
 
     'cvv_enabled' => defined dbdef->table('cust_main')->column('paycvv'),
 
+    'ship_enabled' => defined dbdef->table('cust_main')->column('ship_last'),
+
     'msgcat' => { map { $_=>gettext($_) } qw(
       passwords_dont_match invalid_card unknown_card_type not_a empty_password
     ) },
     'msgcat' => { map { $_=>gettext($_) } qw(
       passwords_dont_match invalid_card unknown_card_type not_a empty_password
     ) },
@@ -102,11 +104,28 @@ sub signup_info {
     }
   }
 
     }
   }
 
-  if ( $agentnum ) {
+  $signup_info->{'part_pkg'} = [];
+  if ( $packet->{'promo_code'} ) {
+    $signup_info->{'part_pkg'} =
+      [ map { { 'payby'   => [ $_->payby ], %{$_->hashref} } }
+          grep { $_->svcpart('svc_acct') }
+            qsearch( 'part_pkg', { 'promo_code' => {
+                                     op=>'ILIKE',
+                                     value=>$packet->{'promo_code'}
+                                   },
+                                   'disabled'   => '',                  } )
+      ];
+
+    $signup_info->{'error'} = 'Unknown promotional code'
+      unless @{ $signup_info->{'part_pkg'} };
+  }
+
+  if ( $agentnum && ! @{ $signup_info->{'part_pkg'} } ) {
     $signup_info->{'part_pkg'} = $signup_info->{'agentnum2part_pkg'}{$agentnum};
     $signup_info->{'part_pkg'} = $signup_info->{'agentnum2part_pkg'}{$agentnum};
-  } else {
-    delete $signup_info->{'part_pkg'};
   }
   }
+  # else {
+  # delete $signup_info->{'part_pkg'};
+  #}
 
   if ( $session ) {
     my $agent_signup_info = { %$signup_info };
 
   if ( $session ) {
     my $agent_signup_info = { %$signup_info };
@@ -158,10 +177,17 @@ sub new_customer {
                        || $conf->config('signup_server-default_refnum'),
 
     map { $_ => $packet->{$_} } qw(
                        || $conf->config('signup_server-default_refnum'),
 
     map { $_ => $packet->{$_} } qw(
-      last first ss company address1 address2 city county state zip country
-      daytime night fax payby payinfo paycvv paydate payname referral_custnum
-      comments
-    ),
+
+      last first ss company address1 address2
+      city county state zip country
+      daytime night fax
+
+      ship_last ship_first ship_ss 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 referral_custnum comments
+    )
 
   } );
 
 
   } );
 
@@ -185,10 +211,11 @@ sub new_customer {
 
   my $cust_pkg = new FS::cust_pkg ( {
     #later#'custnum' => $custnum,
 
   my $cust_pkg = new FS::cust_pkg ( {
     #later#'custnum' => $custnum,
-    'pkgpart' => $packet->{'pkgpart'},
+    'pkgpart'    => $packet->{'pkgpart'},
+    'promo_code' => $packet->{'promo_code'},
   } );
   } );
-  my $error = $cust_pkg->check;
-  return { 'error' => $error } if $error;
+  #my $error = $cust_pkg->check;
+  #return { 'error' => $error } if $error;
 
   my $svc_acct = new FS::svc_acct ( {
     'svcpart'   => $svcpart,
 
   my $svc_acct = new FS::svc_acct ( {
     'svcpart'   => $svcpart,
@@ -214,15 +241,15 @@ sub new_customer {
   my $y = $svc_acct->setdefault; # arguably should be in new method
   return { 'error' => $y } if $y && !ref($y);
 
   my $y = $svc_acct->setdefault; # arguably should be in new method
   return { 'error' => $y } if $y && !ref($y);
 
-  $error = $svc_acct->check;
-  return { 'error' => $error } if $error;
+  #$error = $svc_acct->check;
+  #return { 'error' => $error } if $error;
 
   #setup a job dependancy to delay provisioning
   my $placeholder = new FS::queue ( {
     'job'    => 'FS::ClientAPI::Signup::__placeholder',
     'status' => 'locked',
   } );
 
   #setup a job dependancy to delay provisioning
   my $placeholder = new FS::queue ( {
     'job'    => 'FS::ClientAPI::Signup::__placeholder',
     'status' => 'locked',
   } );
-  $error = $placeholder->insert;
+  my $error = $placeholder->insert;
   return { 'error' => $error } if $error;
 
   use Tie::RefHash;
   return { 'error' => $error } if $error;
 
   use Tie::RefHash;
index f0026d5..5a6bb57 100644 (file)
@@ -1424,7 +1424,7 @@ on the column first.
 sub ut_foreign_key {
   my( $self, $field, $table, $foreign ) = @_;
   qsearchs($table, { $foreign => $self->getfield($field) })
 sub ut_foreign_key {
   my( $self, $field, $table, $foreign ) = @_;
   qsearchs($table, { $foreign => $self->getfield($field) })
-    or return "Can't find $field ". $self->getfield($field).
+    or return "Can't find ". $self->table. ".$field ". $self->getfield($field).
               " in $table.$foreign";
   '';
 }
               " in $table.$foreign";
   '';
 }
index 3bce653..1f1ae40 100644 (file)
@@ -145,32 +145,9 @@ sub table { 'cust_pkg'; }
 Adds this billing item to the database ("Orders" the item).  If there is an
 error, returns the error, otherwise returns false.
 
 Adds this billing item to the database ("Orders" the item).  If there is an
 error, returns the error, otherwise returns false.
 
-=cut
-
-sub insert {
-  my $self = shift;
-
-  # custnum might not have have been defined in sub check (for one-shot new
-  # customers), so check it here instead
-  # (is this still necessary with transactions?)
-
-  my $error = $self->ut_number('custnum');
-  return $error if $error;
-
-  my $cust_main = $self->cust_main;
-  return "Unknown custnum: ". $self->custnum unless $cust_main;
-
-  unless ( $disable_agentcheck ) {
-    my $agent = qsearchs( 'agent', { 'agentnum' => $cust_main->agentnum } );
-    my $pkgpart_href = $agent->pkgpart_hashref;
-    return "agent ". $agent->agentnum.
-           " can't purchase pkgpart ". $self->pkgpart
-      unless $pkgpart_href->{ $self->pkgpart };
-  }
-
-  $self->SUPER::insert;
-
-}
+If the additional field I<promo_code> is defined instead of I<pkgpart>, it
+will be used to look up the package definition and agent restrictions will be
+ignored.
 
 =item delete
 
 
 =item delete
 
@@ -233,8 +210,8 @@ sub check {
 
   my $error = 
     $self->ut_numbern('pkgnum')
 
   my $error = 
     $self->ut_numbern('pkgnum')
-    || $self->ut_numbern('custnum')
-    || $self->ut_number('pkgpart')
+    || $self->ut_foreign_key('custnum', 'cust_main', 'custnum')
+    || $self->ut_numbern('pkgpart')
     || $self->ut_numbern('setup')
     || $self->ut_numbern('bill')
     || $self->ut_numbern('susp')
     || $self->ut_numbern('setup')
     || $self->ut_numbern('bill')
     || $self->ut_numbern('susp')
@@ -242,12 +219,31 @@ sub check {
   ;
   return $error if $error;
 
   ;
   return $error if $error;
 
-  if ( $self->custnum ) { 
-    return "Unknown customer ". $self->custnum unless $self->cust_main;
-  }
+  if ( $self->promo_code ) {
+
+    my $promo_part_pkg =
+      qsearchs('part_pkg', {
+        'pkgpart'    => $self->pkgpart,
+        'promo_code' => { op=>'ILIKE', value=>$self->promo_code },
+      } );
+    return 'Unknown promotional code' unless $promo_part_pkg;
+    $self->pkgpart($promo_part_pkg->pkgpart);
+
+  } else { 
+
+    unless ( $disable_agentcheck ) {
+      my $agent =
+        qsearchs( 'agent', { 'agentnum' => $self->cust_main->agentnum } );
+      my $pkgpart_href = $agent->pkgpart_hashref;
+      return "agent ". $agent->agentnum.
+             " can't purchase pkgpart ". $self->pkgpart
+        unless $pkgpart_href->{ $self->pkgpart };
+    }
 
 
-  return "Unknown pkgpart: ". $self->pkgpart
-    unless qsearchs( 'part_pkg', { 'pkgpart' => $self->pkgpart } );
+    $error = $self->ut_foreign_key('pkgpart', 'part_pkg', 'pkgpart' );
+    return $error if $error;
+
+  }
 
   $self->otaker(getotaker) unless $self->otaker;
   $self->otaker =~ /^([\w\.\-]{0,16})$/ or return "Illegal otaker";
 
   $self->otaker(getotaker) unless $self->otaker;
   $self->otaker =~ /^([\w\.\-]{0,16})$/ or return "Illegal otaker";
index d7cc3cb..2f3cb8b 100644 (file)
@@ -54,6 +54,8 @@ inherits from FS::Record.  The following fields are currently supported:
 
 =item comment - Text name of this package definition (non-customer-viewable)
 
 
 =item comment - Text name of this package definition (non-customer-viewable)
 
+=item promo_code - Promotional code
+
 =item setup - Setup fee expression (deprecated)
 
 =item freq - Frequency of recurring fee
 =item setup - Setup fee expression (deprecated)
 
 =item freq - Frequency of recurring fee
@@ -288,6 +290,7 @@ sub check {
   my $error = $self->ut_numbern('pkgpart')
     || $self->ut_text('pkg')
     || $self->ut_text('comment')
   my $error = $self->ut_numbern('pkgpart')
     || $self->ut_text('pkg')
     || $self->ut_text('comment')
+    || $self->ut_textn('promo_code')
     || $self->ut_alphan('plan')
     || $self->ut_enum('setuptax', [ '', 'Y' ] )
     || $self->ut_enum('recurtax', [ '', 'Y' ] )
     || $self->ut_alphan('plan')
     || $self->ut_enum('setuptax', [ '', 'Y' ] )
     || $self->ut_enum('recurtax', [ '', 'Y' ] )
index 288b086..49953b8 100755 (executable)
@@ -680,6 +680,7 @@ sub tables_hash_hack {
         'pkgpart',    'serial',    '',   '',
         'pkg',        'varchar',   '',   $char_d,
         'comment',    'varchar',   '',   $char_d,
         'pkgpart',    'serial',    '',   '',
         'pkg',        'varchar',   '',   $char_d,
         'comment',    'varchar',   '',   $char_d,
+        'promo_code', 'varchar', 'NULL', $char_d,
         'setup',      @perl_type,
         'freq',       'varchar',   '',   $char_d,  #billing frequency
         'recur',      @perl_type,
         'setup',      @perl_type,
         'freq',       'varchar',   '',   $char_d,  #billing frequency
         'recur',      @perl_type,
@@ -691,8 +692,8 @@ sub tables_hash_hack {
         'taxclass',   'varchar', 'NULL', $char_d,
       ],
       'primary_key' => 'pkgpart',
         'taxclass',   'varchar', 'NULL', $char_d,
       ],
       'primary_key' => 'pkgpart',
-      'unique' => [],
-      'index' => [ [ 'disabled' ], ],
+      'unique' => [ [ 'promo_code' ] ],
+      'index' => [ [ 'disabled' ] ],
     },
 
 #    'part_title' => {
     },
 
 #    'part_title' => {
index 074f3a5..cd7e5a2 100644 (file)
@@ -31,6 +31,11 @@ CREATE TABLE rate_prefix (
 CREATE INDEX rate_prefix1 ON rate_prefix ( countrycode );
 CREATE INDEX rate_prefix2 ON rate_prefix ( regionnum );
 
 CREATE INDEX rate_prefix1 ON rate_prefix ( countrycode );
 CREATE INDEX rate_prefix2 ON rate_prefix ( regionnum );
 
+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 );
+
 dbdef-create username
 create-history-tables username rate rate_detail rate_region rate_prefix
 dbdef-create username
 dbdef-create username
 create-history-tables username rate rate_detail rate_region rate_prefix
 dbdef-create username
index 284fddd..d673030 100644 (file)
@@ -196,7 +196,8 @@ sub popselector {
 =head1 BUGS
 
 This is just a wrapper around FS::SelfService functions for backwards
 =head1 BUGS
 
 This is just a wrapper around FS::SelfService functions for backwards
-compatibility and will probably be deprecated soon.
+compatibility.  It is only necessary if you're using a signup.cgi from before
+1.5.0pre7.
 
 =head1 SEE ALSO
 
 
 =head1 SEE ALSO
 
diff --git a/fs_signup/FS-SignupClient/cgi/promocode.html b/fs_signup/FS-SignupClient/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_signup/FS-SignupClient/cgi/signup-billaddress.html b/fs_signup/FS-SignupClient/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>
index 4f9efff..a1b9ed4 100755 (executable)
@@ -1,14 +1,22 @@
 #!/usr/bin/perl -T
 #!/usr/bin/perl -Tw
 #
 #!/usr/bin/perl -T
 #!/usr/bin/perl -Tw
 #
-# $Id: signup.cgi,v 1.52 2004-10-01 01:38:02 ivan Exp $
+# $Id: signup.cgi,v 1.53 2004-11-22 18:20:21 ivan Exp $
 
 use strict;
 use vars qw( @payby $cgi $locales $packages
              $pops %pop %popnum2pop
              $init_data $error
 
 use strict;
 use vars qw( @payby $cgi $locales $packages
              $pops %pop %popnum2pop
              $init_data $error
-             $last $first $ss $company $address1 $address2 $city $state $county
-             $country $zip $daytime $night $fax $invoicing_list $payby $payinfo
+
+             $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
              $agentnum $refnum
              $paycvv $paydate $payname $referral_custnum $init_popstate
              $pkgpart $username $password $password2 $sec_phrase $popnum
              $agentnum $refnum
@@ -21,14 +29,14 @@ use vars qw( @payby $cgi $locales $packages
              $self_url
            );
 use subs qw( print_form print_okay print_decline
              $self_url
            );
 use subs qw( print_form print_okay print_decline
-             success_default decline_default );
+             success_default decline_default
+           );
 use CGI;
 #use CGI::Carp qw(fatalsToBrowser);
 use Text::Template;
 use Business::CreditCard;
 use HTTP::BrowserDetect;
 use CGI;
 #use CGI::Carp qw(fatalsToBrowser);
 use Text::Template;
 use Business::CreditCard;
 use HTTP::BrowserDetect;
-use FS::SignupClient 0.03 qw( signup_info new_customer
-                              regionselector expselect popselector);
+use FS::SelfService qw( signup_info new_customer expselect );
 
 #acceptable payment methods
 #
 
 #acceptable payment methods
 #
@@ -124,8 +132,13 @@ if ( -e $decline_html ) {
     or die $Text::Template::ERROR;
 }
 
     or die $Text::Template::ERROR;
 }
 
+$cgi = new CGI;
 
 
-( $locales, $packages, $pops, $init_data ) = signup_info();
+$init_data = signup_info( 'promo_code' => $cgi->param('promo_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;
 %pop = ();
 @payby = @{$init_data->{'payby'}} if @{$init_data->{'payby'}};
 $packages = $init_data->{agentnum2part_pkg}{$agentnum} if $agentnum;
 %pop = ();
@@ -135,8 +148,6 @@ foreach (@$pops) {
   $popnum2pop{$_->{popnum}} = $_;
 }
 
   $popnum2pop{$_->{popnum}} = $_;
 }
 
-$cgi = new CGI;
-
 if ( defined $cgi->param('magic') ) {
   if ( $cgi->param('magic') eq 'process' ) {
 
 if ( defined $cgi->param('magic') ) {
   if ( $cgi->param('magic') eq 'process' ) {
 
@@ -193,6 +204,22 @@ if ( defined $cgi->param('magic') ) {
     $daytime          = $cgi->param('daytime');
     $night            = $cgi->param('night');
     $fax              = $cgi->param('fax');
     $daytime          = $cgi->param('daytime');
     $night            = $cgi->param('night');
     $fax              = $cgi->param('fax');
+
+    $ship_last        = $cgi->param('ship_last');
+    $ship_first       = $cgi->param('ship_first');
+    $ship_ss          = $cgi->param('ship_ss');
+    $ship_company     = $cgi->param('ship_company');
+    $ship_address1    = $cgi->param('ship_address1');
+    $ship_address2    = $cgi->param('ship_address2');
+    $ship_city        = $cgi->param('ship_city');
+    #$ship_county,
+    #$ship_state,
+    $ship_zip         = $cgi->param('ship_zip');
+    #$ship_country,
+    $ship_daytime     = $cgi->param('ship_daytime');
+    $ship_night       = $cgi->param('ship_night');
+    $ship_fax         = $cgi->param('ship_fax');
+
     #$payby,
     #$payinfo,
     #$paydate,
     #$payby,
     #$payinfo,
     #$paydate,
@@ -228,37 +255,56 @@ if ( defined $cgi->param('magic') ) {
           or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
       }
 
           or $error ||= $init_data->{msgcat}{not_a}. $cgi->param('CARD_type');
       }
 
-      $error ||= new_customer ( {
-        'last'             => $last,
-        'first'            => $first,
-        'ss'               => $ss,
-        'company'          => $company,
-        'address1'         => $address1,
-        'address2'         => $address2,
-        'city'             => $city,
-        'county'           => $county,
-        'state'            => $state,
-        'zip'              => $zip,
-        'country'          => $country,
-        'daytime'          => $daytime,
-        'night'            => $night,
-        'fax'              => $fax,
-        'payby'            => $payby,
-        'payinfo'          => $payinfo,
-        'paycvv'           => $paycvv,
-        'paydate'          => $paydate,
-        'payname'          => $payname,
-        'invoicing_list'   => $invoicing_list,
-        'referral_custnum' => $referral_custnum,
-        'pkgpart'          => $pkgpart,
-        'username'         => $username,
-        'sec_phrase'       => $sec_phrase,
-        '_password'        => $password,
-        'popnum'           => $popnum,
-        'agentnum'         => $agentnum,
-        'refnum'           => $refnum,
-        map { $_ => $cgi->param($_) } grep { /^snarf_/ } $cgi->param
-      } );
+      unless ( $error ) {
+
+        my $r = new_customer ( {
+          'last'             => $last,
+          'first'            => $first,
+          'ss'               => $ss,
+          'company'          => $company,
+          'address1'         => $address1,
+          'address2'         => $address2,
+          'city'             => $city,
+          'county'           => $county,
+          'state'            => $state,
+          'zip'              => $zip,
+          'country'          => $country,
+          'daytime'          => $daytime,
+          'night'            => $night,
+          'fax'              => $fax,
+          'ship_last'        => $ship_last,
+          'ship_first'       => $ship_first,
+          'ship_company'     => $ship_company,
+          'ship_address1'    => $ship_address1,
+          'ship_address2'    => $ship_address2,
+          'ship_city'        => $ship_city,
+          'ship_county'      => $ship_county,
+          'ship_state'       => $ship_state,
+          'ship_zip'         => $ship_zip,
+          'ship_country'     => $ship_country,
+          'ship_daytime'     => $ship_daytime,
+          'ship_night'       => $ship_night,
+          'ship_fax'         => $ship_fax,
+          'payby'            => $payby,
+          'payinfo'          => $payinfo,
+          'paycvv'           => $paycvv,
+          'paydate'          => $paydate,
+          'payname'          => $payname,
+          'invoicing_list'   => $invoicing_list,
+          'referral_custnum' => $referral_custnum,
+          'promo_code'       => $cgi->param('promo_code'),
+          'pkgpart'          => $pkgpart,
+          'username'         => $username,
+          'sec_phrase'       => $sec_phrase,
+          '_password'        => $password,
+          'popnum'           => $popnum,
+          'agentnum'         => $agentnum,
+          'refnum'           => $refnum,
+          map { $_ => $cgi->param($_) } grep { /^snarf_/ } $cgi->param
+        } );
+        $error ||= $r->{'error'};
+
+      }
 
     }
     
 
     }
     
@@ -277,7 +323,7 @@ if ( defined $cgi->param('magic') ) {
     die "unrecognized magic: ". $cgi->param('magic');
   }
 } else {
     die "unrecognized magic: ". $cgi->param('magic');
   }
 } else {
-  $error = '';
+  #$error = '';
   $last = '';
   $first = '';
   $ss = '';
   $last = '';
   $first = '';
   $ss = '';
@@ -292,6 +338,19 @@ if ( defined $cgi->param('magic') ) {
   $daytime = '';
   $night = '';
   $fax = '';
   $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 = '';
   $invoicing_list = '';
   $payby = '';
   $payinfo = '';
@@ -331,17 +390,17 @@ sub print_okay {
   my $user_agent = new HTTP::BrowserDetect $ENV{HTTP_USER_AGENT};
 
   $cgi->param('username') =~ /^(.+)$/
   my $user_agent = new HTTP::BrowserDetect $ENV{HTTP_USER_AGENT};
 
   $cgi->param('username') =~ /^(.+)$/
-    or die "fatal: invalid username got past FS::SignupClient::new_customer";
+    or die "fatal: invalid username got past FS::SelfService::new_customer";
   my $username = $1;
   $cgi->param('_password') =~ /^(.+)$/
   my $username = $1;
   $cgi->param('_password') =~ /^(.+)$/
-    or die "fatal: invalid password got past FS::SignupClient::new_customer";
+    or die "fatal: invalid password got past FS::SelfService::new_customer";
   my $password = $1;
   ( $cgi->param('first'). ' '. $cgi->param('last') ) =~ /^(.*)$/
   my $password = $1;
   ( $cgi->param('first'). ' '. $cgi->param('last') ) =~ /^(.*)$/
-    or die "fatal: invalid email_name got past FS::SignupClient::new_customer";
+    or die "fatal: invalid email_name got past FS::SelfService::new_customer";
   $email_name = $1; #global for template
 
   my $pop = $popnum2pop{$cgi->param('popnum')};
   $email_name = $1; #global for template
 
   my $pop = $popnum2pop{$cgi->param('popnum')};
-    #or die "fatal: invalid popnum got past FS::SignupClient::new_customer";
+    #or die "fatal: invalid popnum got past FS::SelfService::new_customer";
   if ( $pop ) {
     ( $ac, $exch, $loc ) = ( $pop->{'ac'}, $pop->{'exch'}, $pop->{'loc'} );
   } else {
   if ( $pop ) {
     ( $ac, $exch, $loc ) = ( $pop->{'ac'}, $pop->{'exch'}, $pop->{'loc'} );
   } else {
@@ -387,3 +446,40 @@ support.
 END
 }
 
 END
 }
 
+# subs for the templates...
+
+=item regionselector SELECTED_COUNTY, SELECTED_STATE, SELECTED_COUNTRY, PREFIX, ONCHANGE
+
+=cut
+
+sub regionselector {
+  my ( $selected_county, $selected_state, $selected_country,
+       $prefix, $onchange ) = @_;
+  signup_info() unless $init_data;
+  FS::SelfService::regionselector({
+    selected_county  => $selected_county,
+    selected_state   => $selected_state,
+    selected_country => $selected_country,
+    prefix           => $prefix,
+    onchange         => $onchange,
+    default_country  => $init_data->{countrydefault},
+    locales          => $init_data->{cust_main_county},
+  });
+    #default_state    => $init_data->{statedefault},
+}
+
+=item popselector 
+
+=cut
+
+sub popselector {
+  my( $popnum ) = @_;
+  signup_info() unless $init_data;
+  FS::SelfService::popselector({
+    popnum => $popnum,
+    pops   => $init_data->{svc_acct_pop},
+  });
+    #popac =>
+    #acstate =>
+}
+
index a6cbf21..c0e4f73 100755 (executable)
@@ -167,14 +167,17 @@ Contact Information
 
 </TR></TABLE><font color="#ff0000">*</font> required fields for each billing type
 <BR><BR>First package
 
 </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%">
+<INPUT TYPE="hidden" NAME="promo_code" VALUE="<%= $cgi->param('promo_code') %>"><TABLE BGCOLOR="#c0c0c0" BORDER=0 CELLSPACING=0 WIDTH="100%">
 <TR>
 <TR>
-  <TD COLSPAN=2><SELECT NAME="pkgpart"><OPTION VALUE="">(none)
+  <TD COLSPAN=2><SELECT NAME="pkgpart">
 
   <%=
 
   <%=
+    $OUT .= '<OPTION VALUE="">(none)' unless scalar(@$packages) == 1;
     foreach my $package ( @{$packages} ) {
       $OUT .= '<OPTION VALUE="'. $package->{'pkgpart'}. '"';
     foreach my $package ( @{$packages} ) {
       $OUT .= '<OPTION VALUE="'. $package->{'pkgpart'}. '"';
-      $OUT .= ' SELECTED' if $pkgpart && $package->{'pkgpart'} == $pkgpart;
+      $OUT .= ' SELECTED'
+        if ( $pkgpart && $package->{'pkgpart'} == $pkgpart )
+           || scalar(@$packages) == 1;
       $OUT .= '>'. $package->{'pkg'};
     }
   %>
       $OUT .= '>'. $package->{'pkg'};
     }
   %>
index 2e78f6e..c5cfd51 100644 (file)
         <li>pkgpart - primary key
         <li>pkg - package name
         <li>comment - non-customer visable package comment
         <li>pkgpart - primary key
         <li>pkg - package name
         <li>comment - non-customer visable package comment
-        <li>setup - setup fee expression
+        <li>promo_code - promotional code
+        <li><i>deprecated</i> setup - setup fee expression
         <li>freq - recurring frequency (months)
         <li>freq - recurring frequency (months)
-        <li>recur - recurring fee expression
+        <li><i>deprecated</i> recur - recurring fee expression
         <li>setuptax - Setup fee tax exempt flag, empty or `Y'
         <li>recurtax - Recurring fee tax exempt flag, empty or `Y'
         <li>plan - price plan
         <li>setuptax - Setup fee tax exempt flag, empty or `Y'
         <li>recurtax - Recurring fee tax exempt flag, empty or `Y'
         <li>plan - price plan
-        <li>plandata - additional price plan data
+        <li><i>deprecated</i> plandata - additional price plan data
         <li>disabled - Disabled flag, empty or `Y'
       </ul>
     <li><a name="part_pkg_option" href="man/FS/part_pkg_option.html">part_pkg_option</a> - Package definition options
         <li>disabled - Disabled flag, empty or `Y'
       </ul>
     <li><a name="part_pkg_option" href="man/FS/part_pkg_option.html">part_pkg_option</a> - Package definition options
index e17f7ad..9dacf91 100644 (file)
@@ -250,6 +250,10 @@ ALTER TABLE pkg_svc ADD primary_svc char(1) NULL;
 ALTER TABLE h_pkg_svc ADD primary_svc char(1) NULL;
 ALTER TABLE svc_forward ADD src varchar(255) NULL;
 ALTER TABLE h_svc_forward ADD src varchar(255) NULL;
 ALTER TABLE h_pkg_svc ADD primary_svc char(1) NULL;
 ALTER TABLE svc_forward ADD src varchar(255) NULL;
 ALTER TABLE h_svc_forward ADD src varchar(255) NULL;
+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 );
 
 On recent Pg versions:
 
 
 On recent Pg versions:
 
index 4a8f705..f5826f3 100755 (executable)
@@ -168,8 +168,8 @@ print "<BR><BR>Billing address", &itable("#cccccc"), <<END;
 END
 
 print <<END;
 END
 
 print <<END;
-<INPUT TYPE="text" NAME="last" VALUE="$last"> , 
-<INPUT TYPE="text" NAME="first" VALUE="$first">
+<INPUT TYPE="text" NAME="last" VALUE="$last" onChange="changed(this)"> , 
+<INPUT TYPE="text" NAME="first" VALUE="$first" onChange="changed(this)">
 </TD>
 END
 
 </TD>
 END
 
@@ -181,10 +181,10 @@ if ( $conf->exists('show_ss') ) {
 
 print <<END;
 </TR>
 
 print <<END;
 </TR>
-<TR><TD ALIGN="right">Company</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="company" VALUE="$company" SIZE=70></TD></TR>
-<TR><TH ALIGN="right">${r}Address</TH><TD COLSPAN=5><INPUT TYPE="text" NAME="address1" VALUE="$address1" SIZE=70></TD></TR>
-<TR><TD ALIGN="right">&nbsp;</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="address2" VALUE="$address2" SIZE=70></TD></TR>
-<TR><TH ALIGN="right">${r}City</TH><TD><INPUT TYPE="text" NAME="city" VALUE="$city"></TD><TH ALIGN="right">${r}State</TH><TD>
+<TR><TD ALIGN="right">Company</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="company" VALUE="$company" SIZE=70 onChange="changed(this)"></TD></TR>
+<TR><TH ALIGN="right">${r}Address</TH><TD COLSPAN=5><INPUT TYPE="text" NAME="address1" VALUE="$address1" SIZE=70 onChange="changed(this)"></TD></TR>
+<TR><TD ALIGN="right">&nbsp;</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="address2" VALUE="$address2" SIZE=70 onChange="changed(this)"></TD></TR>
+<TR><TH ALIGN="right">${r}City</TH><TD><INPUT TYPE="text" NAME="city" VALUE="$city" onChange="changed(this)"></TD><TH ALIGN="right">${r}State</TH><TD>
 END
 
 #false laziness with ship state
 END
 
 #false laziness with ship state
@@ -203,12 +203,14 @@ my($county_html, $state_html, $country_html) =
 
 print "$county_html $state_html";
 
 
 print "$county_html $state_html";
 
-print qq!</TD><TH>${r}Zip</TH><TD><INPUT TYPE="text" NAME="zip" VALUE="$zip" SIZE=10></TD></TR>!;
+print qq!</TD><TH>${r}Zip</TH><TD><INPUT TYPE="text" NAME="zip" VALUE="$zip" SIZE=10 onChange="changed(this)"></TD></TR>!;
 
 my($daytime,$night,$fax)=(
   $cust_main->daytime,
   $cust_main->night,
   $cust_main->fax,
 
 my($daytime,$night,$fax)=(
   $cust_main->daytime,
   $cust_main->night,
   $cust_main->fax,
+  '',
+  'changed(this)',
 );
 
 my $daytime_label = FS::Msgcat::_gettext('daytime') || 'Day Phone';
 );
 
 my $daytime_label = FS::Msgcat::_gettext('daytime') || 'Day Phone';
@@ -216,9 +218,9 @@ my $night_label = FS::Msgcat::_gettext('night') || 'Night Phone';
 
 print <<END;
 <TR><TH ALIGN="right">${r}Country</TH><TD>$country_html</TD></TR>
 
 print <<END;
 <TR><TH ALIGN="right">${r}Country</TH><TD>$country_html</TD></TR>
-<TR><TD ALIGN="right">$daytime_label</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="daytime" VALUE="$daytime" SIZE=18></TD></TR>
-<TR><TD ALIGN="right">$night_label</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>
+<TR><TD ALIGN="right">$daytime_label</TD><TD COLSPAN=5><INPUT TYPE="text" NAME="daytime" VALUE="$daytime" SIZE=18 onChange="changed(this)"></TD></TR>
+<TR><TD ALIGN="right">$night_label</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>
 END
 
 print "</TABLE>${r}required fields<BR>";
 END
 
 print "</TABLE>${r}required fields<BR>";
index dc29924..b3c389c 100755 (executable)
@@ -93,7 +93,12 @@ Package information
       <INPUT TYPE="text" NAME="comment" SIZE=32 VALUE="<%=$part_pkg->comment%>">
     </TD>
   </TR>
       <INPUT TYPE="text" NAME="comment" SIZE=32 VALUE="<%=$part_pkg->comment%>">
     </TD>
   </TR>
-
+  <TR>
+    <TD ALIGN="right">Promotional code</TD>
+    <TD>
+      <INPUT TYPE="text" NAME="promo_code" SIZE=32 VALUE="<%=$part_pkg->promo_code%>">
+    </TD>
+  </TR>
   <TR>
     <TD ALIGN="right">Disable new orders</TD>
     <TD>
   <TR>
     <TD ALIGN="right">Disable new orders</TD>
     <TD>
@@ -257,7 +262,9 @@ my $widget = new HTML::Widgets::SelectLayers(
   'options'        => \%options,
   'form_name'      => 'dummy',
   'form_action'    => 'process/part_pkg.cgi',
   'options'        => \%options,
   'form_name'      => 'dummy',
   'form_action'    => 'process/part_pkg.cgi',
-  'form_text'      => [ qw(pkg comment clone pkgnum pkgpart), @fixups ],
+  'form_text'      => [ qw(pkg comment promo_code clone pkgnum pkgpart),
+                        @fixups
+                      ],
   'form_checkbox'  => [ qw(setuptax recurtax disabled) ],
   'form_radio'     => \@form_radio,
   'form_select'    => \@form_select,
   'form_checkbox'  => [ qw(setuptax recurtax disabled) ],
   'form_radio'     => \@form_radio,
   'form_select'    => \@form_select,