0.14_26 commit r0_14_26
authorTony Cook <tony@develop-help.com>
Fri, 20 Aug 2004 07:03:22 +0000 (07:03 +0000)
committertony <tony@45cb6cf1-00bc-42d2-bb5a-07f51df49f94>
Fri, 20 Aug 2004 07:03:22 +0000 (07:03 +0000)
12 files changed:
Makefile
schema/bse.sql
site/cgi-bin/modules/BSE/AdminSiteUsers.pm
site/cgi-bin/modules/BSE/DB/Mysql.pm
site/cgi-bin/modules/BSE/UI/Affiliate.pm
site/cgi-bin/modules/BSE/UserReg.pm
site/cgi-bin/modules/SiteUser.pm
site/cgi-bin/shop.pl
site/docs/bse.pod
site/templates/admin/users/edit.tmpl
site/templates/user/options_base.tmpl
test.cfg

index 18b188d..a6c92f2 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-VERSION=0.14_25
+VERSION=0.14_26
 DISTNAME=bse-$(VERSION)
 DISTBUILD=$(DISTNAME)
 DISTTAR=../$(DISTNAME).tar
index 6c86f72..ec91568 100644 (file)
@@ -491,8 +491,11 @@ create table site_users (
   customStr2 varchar(255),
   customStr3 varchar(255),
 
+  affiliate_name varchar(40) not null default '',
+
   primary key (id),
-  unique (userId)
+  unique (userId),
+  index (affiliate_name)
 );
 
 -- this is used to track email addresses that we've sent subscription
@@ -617,3 +620,17 @@ create table admin_perms (
 --   primary key (subscription_id, siteuser_id)
 -- );
 
+drop table if exists bse_siteuser_images;
+create table bse_siteuser_images (
+  siteuser_id integer not null,
+  image_id varchar(20) not null,
+  filename varchar(80) not null,
+  width integer not null,
+  height integer not null,
+  bytes integer not null,
+  content_type varchar(80) not null,
+  alt varchar(255) not null,
+
+  primary key(siteuser_id, image_id)
+);
+
index 29f0220..d0cc3df 100644 (file)
@@ -18,7 +18,7 @@ my %actions =
    add=>1,
   );
 
-my @donttouch = qw(id userId password email confirmed confirmSecret waitingForConfirmation flags); # flags is saved separately
+my @donttouch = qw(id userId password email confirmed confirmSecret waitingForConfirmation flags affiliate_name); # flags is saved separately
 my %donttouch = map { $_, $_ } @donttouch;
 
 sub dispatch {
@@ -301,6 +301,23 @@ sub req_save {
     }
   }
 
+  my $aff_name = $cgi->param('affiliate_name');
+  if (defined $aff_name && length $aff_name) {
+    if ($aff_name =~ /^\s*\w+\s*$/) {
+      $aff_name =~ s/^\s+|\s+$//g;
+      my $other = SiteUsers->getBy(affiliate_name => $aff_name);
+      if ($other) {
+       $errors{affiliate_name} = "affiliate name $aff_name is already in use";
+      }
+    }
+    else {
+      $errors{affiliate_name} = "invalid affiliate name, no spaces or special characters are allowed";
+    }
+  }
+  else {
+    undef $aff_name;
+  }
+
   keys %errors
     and return $class->req_edit($req, undef, \%errors);
   
@@ -314,6 +331,8 @@ sub req_save {
   }
   $user->{password} = $newpass if !$nopassword && $newpass;
   
+  $user->{affiliate_name} = $aff_name if defined $aff_name;
+  
   for my $col (@cols) {
     my $value = $cgi->param($col);
     if (defined $value) {
index 4797fd3..beae019 100644 (file)
@@ -117,8 +117,10 @@ SQL
    'select * from site_users where userId = ?',
    getSiteUserByPkey =>
    'select * from site_users where id = ?',
-   addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
-   replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+   getSiteUserByAffiliate_name =>
+   'select * from site_users where affiliate_name = ?',
+   addSiteUser => 'insert site_users values(null,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
+   replaceSiteUser => 'replace site_users values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)',
    'SiteUsers.removeSubscriptions'=>
    'delete from subscribed_users where userId = ?',
    'SiteUsers.removeSub'=>
@@ -128,6 +130,22 @@ select si.* from site_users si, subscribed_users su
   where confirmed <> 0 and disabled = 0 and si.id = su.userId and su.subId = ?
 EOS
    SiteUsers => 'select * from site_users',
+   getBSESiteuserImage => <<SQL,
+select * from bse_siteuser_images
+  where siteuser_id = ? and image_id = ?
+SQL
+   getBSESiteuserImages => <<SQL,
+select * from bse_siteuser_images where siteuser_id = ?
+SQL
+   addBSESiteuserImage => <<SQL,
+insert bse_siteuser_images values(?,?,?,?,?,?,?,?)
+SQL
+   replaceBSESiteuserImage => <<SQL,
+replace bse_siteuser_images values(?,?,?,?,?,?,?,?)
+SQL
+   deleteBSESiteuserImage=> <<SQL,
+delete from bse_siteuser_images where member_id = ? and image_id = ?
+SQL
 
    SubscriptionTypes =>
    'select * from subscription_types',
index 9471f3c..64a1e51 100644 (file)
@@ -26,6 +26,10 @@ BSE::UI::Affiliate - set the affiliate code for new orders or display a user inf
 
 http://your.site.com/cgi-bin/affiliate.pl?id=I<number>
 
+http://your.site.com/cgi-bin/affiliate.pl?lo=I<logon>
+
+http://your.site.com/cgi-bin/affiliate.pl?co=I<affiliate name>
+
 # set the stored affiliate code and refresh to the top of the site
 
 http://your.site.com/cgi-bin/affiliate.pl?a_set=1&id=I<code>
@@ -82,7 +86,7 @@ sub req_set {
     my @allowed = split /;/, $allowed_referer;
     my $referer = $ENV{HTTP_REFERER};
     if ($referer) {
-      my ($domain) = ($referer =~ m!^\w+://([\w/]+)!);
+      my ($domain) = ($referer =~ m!^\w+://([\w.]+)!);
       $domain = lc $domain;
       my $found = 0;
       for my $entry (@allowed) {
@@ -178,7 +182,9 @@ sub req_set2 {
 
 =item a_show
 
-Display the affiliate page based on a user id number.
+Display the affiliate page based on a either a user id number supplied
+in the C<id> paramater, a logon name supplied in the C<lo> parameter
+or an affiliate name supplied in the C<co> parameter.
 
 This is the default target, so you do not need to supply a target
 parameter.
@@ -198,11 +204,23 @@ sub req_show {
   my $cgi = $req->cgi;
   my $cfg = $req->cfg;
 
-  my $id = $cgi->param('id');
-  defined $id
-    or return $class->req_none($req, "No identifier supplied");
   require SiteUsers;
-  my $user = SiteUsers->getByPkey($id);
+  my $user;
+  my $id = $cgi->param('id');
+  my $lo = $cgi->param('lo');
+  my $co = $cgi->param('co');
+  if (defined $id && length $id && $id =~ /^\d+$/) {
+    $user = SiteUsers->getByPkey($id);
+  }
+  elsif (defined $lo && length $lo && $lo =~ /^\w+$/) {
+    $user = SiteUsers->getBy(userId => $lo);
+  }
+  elsif (defined $co && length $co && $co =~ /^\w+$/) {
+    $user = SiteUsers->getBy(affiliate_name => $co);
+  }
+  else {
+    return $class->req_none($req, "No identifier supplied");
+  }
   $user
     or return $class->req_none($req, "Unknown user");
 #  require BSE::TB::Subscriptions;
index 07eae73..0459d2d 100644 (file)
@@ -17,7 +17,7 @@ use BSE::WebUtil qw/refresh_to/;
 use constant MAX_UNACKED_CONF_MSGS => 3;
 use constant MIN_UNACKED_CONF_GAP => 2 * 24 * 60 * 60;
 
-my @donttouch = qw(id userId password email confirmed confirmSecret waitingForConfirmation disabled flags);
+my @donttouch = qw(id userId password email confirmed confirmSecret waitingForConfirmation disabled flags affiliate_name);
 my %donttouch = map { $_, $_ } @donttouch;
 
 sub user_tags {
@@ -523,6 +523,26 @@ sub saveopts {
       }
     }
   }
+
+  my $aff_name = $cgi->param('affiliate_name');
+  if (defined $aff_name && length $aff_name) {
+    if ($aff_name =~ /^\s*\w+\s*$/) {
+      $aff_name =~ s/^\s+|\s+$//g;
+      my $other = SiteUsers->getBy(affiliate_name => $aff_name);
+      if ($other) {
+       $errors{affiliate_name} = $msgs->(dupaffiliatename =>
+                                         "affiliate name $aff_name is already in use", $aff_name);
+      }
+    }
+    else {
+      $errors{affiliate_name} = $msgs->(badaffiliatename =>
+                                       "invalid affiliate name, no spaces or special characters are allowed");
+    }
+  }
+  else {
+    undef $aff_name;
+  }
+
   keys %errors
     and return $self->show_opts($session, $cgi, $cfg, undef, \%errors);
   my $newemail;
@@ -534,6 +554,8 @@ sub saveopts {
     ++$newemail;
   }
   $user->{password} = $newpass if !$nopassword && $newpass;
+
+  $user->{affiliate_name} = $aff_name if defined $aff_name;
   
   for my $col (@cols) {
     my $value = $cgi->param($col);
index 43aa945..a99a189 100644 (file)
@@ -20,7 +20,8 @@ sub columns {
             billPostCode billCountry instructions billTelephone billFacsimile 
             billEmail adminNotes disabled flags
             customText1 customText2 customText3
-            customStr1 customStr2 customStr3/;
+            customStr1 customStr2 customStr3
+            affiliate_name/;
 }
 
 sub removeSubscriptions {
@@ -177,4 +178,83 @@ sub subscribed_to_grace {
   return; # PH for now, not subscribed
 }
 
+my @image_cols = 
+  qw(siteuser_id image_id filename width height bytes content_type alt);
+
+sub images_cfg {
+  my ($self, $cfg) = @_;
+
+  my @images;
+  my %ids = $cfg->entries('BSE Siteuser Images');
+  for my $id (keys %ids) {
+    my %image = ( id => $id );
+
+    my $sect = "BSE Siteuser Image $id";
+    for my $key (qw(description help minwidth minheight maxwidth maxheight
+                    minratio maxratio properror 
+                    widthsmallerror heightsmallerror smallerror
+                    widthlargeerror heightlargeerror largeerror
+                    maxspace spaceerror)) {
+      my $value = $cfg->entry($sect, $key);
+      if (defined $value) {
+       $image{$key} = $value;
+      }
+    }
+    push @images, \%image;
+  }
+  
+  @images;
+}
+
+sub images {
+  my ($self) = @_;
+
+  BSE::DB->query(getBSESiteuserImages => $self->{id});
+}
+
+sub get_image {
+  my ($self, $id) = @_;
+
+  my ($image) = BSE::DB->query(getBSESiteuserImage => $self->{id}, $id)
+    or return;
+
+  $image;
+}
+
+sub set_image {
+  my ($self, $cfg, $id, $image) = @_;
+
+  my %image = %$image;
+  $image{siteuser_id} = $self->{id};
+  my $old = $self->get_image($id);
+
+  if ($old) {
+    # replace it
+    BSE::DB->run(replaceBSESiteuserImage => @image{@image_cols});
+
+    # lose the old file
+    my $image_dir = $cfg->entryVar('paths', 'siteuser_images');
+    unlink "$image_dir/$old->{filename}";
+  }
+  else {
+    # add it
+    # replace it
+    BSE::DB->run(addBSESiteuserImage => @image{@image_cols});
+  }
+}
+
+sub remove_image {
+  my ($self, $cfg, $id) = @_;
+
+  if (my $old = $self->get_image($id)) {
+    # remove the entry
+    BSE::DB->run(deleteBSESiteuserImage => $self->{id}, $id);
+    
+    # lose the old file
+    my $image_dir = $cfg->entryVar('paths', 'siteuser_images');
+    unlink "$image_dir/$old->{filename}";
+  }
+}
+
+
 1;
index e4b7515..c86df6c 100755 (executable)
@@ -19,6 +19,7 @@ use BSE::Shop::Util qw/shop_cart_tags cart_item_opts nice_options total
 use BSE::Session;
 use BSE::Cfg;
 use BSE::Util::Tags qw(tag_hash);
+use DevHelp::HTML;
 
 my $cfg = BSE::Cfg->new();
 
@@ -321,6 +322,9 @@ sub checkout {
   $olddata and $payment = param('paymentType');
   defined $payment or $payment = $payment_types[0];
 
+  my $affiliate_code = $session{affiliate_code};
+  defined $affiliate_code or $affiliate_code = '';
+
   my $item_index = -1;
   my @options;
   my $option_index;
@@ -356,6 +360,7 @@ sub checkout {
      user => $user ? [ \&tag_hash, $user ] : '',
      checkedPayment => [ \&tag_checkedPayment, $payment, \%types_by_name ],
      ifPayments => [ \&tag_ifPayments, \@payment_types, \%types_by_name ],
+     affiliate_code => escape_html($affiliate_code),
     );
   for my $type (@pay_types) {
     my $id = $type->{id};
@@ -401,205 +406,6 @@ sub checkout_confirm {
   page('checkoutconfirm.tmpl', \%acts);
 }
 
-# this can be used instead of the purchase page to work in 2 steps:
-#  - collect shipping details
-#  - collect CC details
-# the collection of the CC details should go to another script that 
-# processes the CC information and then displays the order complete
-# information
-# BUG!!: this duplicates the code in purchase() a great deal
-# sub prePurchase {
-
-#   my $cust_class = custom_class($cfg);
-#   my @required = $cust_class->required_fields($CGI::Q, $session{custom}, $cfg);
-#   for my $field (@required) {
-#     defined(param($field)) && length(param($field))
-#       or return checkout("Field $field is required", 1);
-#   }
-#   if (grep /email/, @required) {
-#     defined(param('email')) && param('email') =~ /.\@./
-#       or return checkout("Please enter a valid email address", 1);
-#   }
-  
-#   use BSE::TB::Orders;
-#   use BSE::TB::OrderItems;
-
-#   # map some form fields to order field names
-#   my %field_map = 
-#     (
-#      name1 => 'delivFirstName',
-#      name2 => 'delivLastName',
-#      address => 'delivStreet',
-#      city => 'delivSuburb',
-#      postcode => 'delivPostCode',
-#      state => 'delivState',
-#      country => 'delivCountry',
-#      email => 'emailAddress',
-#      cardHolder => 'ccName',
-#      cardType => 'ccType',
-#     );
-#   # paranoia, don't store these
-#   my %nostore =
-#     (
-#      cardNumber => 1,
-#      cardExpiry => 1,
-#     );
-#   my %order;
-#   my @cart = @{$session{cart}};
-#   @cart or return show_cart('You have no items in your shopping cart');
-
-#   # so we can quickly check for columns
-#   my @columns = BSE::TB::Order->columns;
-#   my %columns; 
-#   @columns{@columns} = @columns;
-
-#   for my $field (param()) {
-#     $order{$field_map{$field} || $field} = param($field)
-#       unless $nostore{$field};
-#   }
-
-#   my $ccNumber = param('cardNumber');
-#   my $ccExpiry = param('cardExpiry');
-
-#   use Digest::MD5 'md5_hex';
-#   $ccNumber =~ tr/0-9//cd;
-#   $order{ccNumberHash} = md5_hex($ccNumber);
-#   $order{ccExpiryHash} = md5_hex($ccExpiry);
-
-#   # work out totals
-#   $order{total} = 0;
-#   $order{gst} = 0;
-#   $order{wholesale} = 0;
-#   my @products;
-#   my $today = epoch_to_sql(time);
-#   for my $item (@cart) {
-#     my $product = Products->getByPkey($item->{productId});
-#     # double check that it's still a valid product
-#     if (!$product) {
-#       return show_cart("Product $item->{productId} not found");
-#     }
-#     else {
-#       (my $comp_release = $product->{release}) =~ s/ .*//;
-#       (my $comp_expire = $product->{expire}) =~ s/ .*//;
-#       $comp_release le $today
-#      or return show_cart("'$product->{title}' has not been released yet");
-#       $today le $comp_expire
-#      or return show_cart("'$product->{title}' has expired");
-#       $product->{listed} 
-#      or return show_cart("'$product->{title}' not available");
-#     }
-#     push(@products, $product); # used in page rendering
-#     @$item{qw/price wholesalePrice gst/} = 
-#       @$product{qw/retailPrice wholesalePrice gst/};
-#     $order{total} += $item->{price} * $item->{units};
-#     $order{wholesale} += $item->{wholesalePrice} * $item->{units};
-#     $order{gst} += $item->{gst} * $item->{units};
-#   }
-#   use BSE::Util::SQL qw(now_sqldatetime);
-#   $order{orderDate} = now_sqldatetime();
-
-#   if (my ($msg, $id) = need_logon($cfg, \@cart, \@products, \%session, $CGI::Q)) {
-#     refresh_logon($msg, $id);
-#     return;
-#   }
-
-#   $order{total} += $cust_class->total_extras(\@cart, \@products, 
-#                                           $session{custom}, $cfg, 'final');
-#   ++$session{changed};
-#   # blank anything else
-#   for my $column (@columns) {
-#     defined $order{$column} or $order{$column} = '';
-#   }
-#   # make sure the user can't set these behind our backs
-#   $order{filled} = 0;
-#   $order{paidFor} = 0;
-  
-#   # this should be hard to guess
-#   $order{randomId} = md5_hex(time().rand().{}.$$);
-
-#   # check if a customizer has anything to do
-#   eval {
-#     $cust_class->order_save($CGI::Q, \%order, \@cart, \@products, 
-#                          $session{custom}, $cfg);
-#     ++$session{changed};
-#   };
-#   if ($@) {
-#     return checkout($@, 1);
-#   }
-
-#   # load up the database
-#   my @data = @order{@columns};
-#   shift @data; # lose the dummy id
-#   my $order = BSE::TB::Orders->add(@data)
-#     or die "Cannot add order";
-#   my @items;
-#   my @item_cols = BSE::TB::OrderItem->columns;
-#   for my $row (@cart) {
-#     $row->{orderId} = $order->{id};
-#     my @data = @$row{@item_cols};
-#     shift @data;
-#     push(@items, BSE::TB::OrderItems->add(@data));
-#   }
-
-#   my $item_index = -1;
-#   my @options;
-#   my $option_index;
-#   my %acts;
-#   %acts =
-#     (
-#      iterate_items_reset => sub { $item_index = -1; },
-#      iterate_items => 
-#      sub { 
-#        if (++$item_index < @items) {
-#       $option_index = -1;
-#       @options = cart_item_opts($items[$item_index], 
-#                                 $products[$item_index]);
-#       return 1;
-#        }
-#        return 0;
-#      },
-#      item=> sub { CGI::escapeHTML($items[$item_index]{$_[0]}); },
-#      product => 
-#      sub { 
-#        my $value = $products[$item_index]{$_[0]};
-#        defined($value) or $value = '';
-#        CGI::escapeHTML($value);
-#      },
-#      extended =>
-#      sub { 
-#        my $what = $_[0] || 'retailPrice';
-#        $items[$item_index]{units} * $items[$item_index]{$what};
-#      },
-#      order => sub { CGI::escapeHTML($order->{$_[0]}) },
-#      money =>
-#      sub {
-#        my ($func, $args) = split ' ', $_[0], 2;
-#        $acts{$func} || return "<: money $_[0] :>";
-#        return sprintf("%.02f", $acts{$func}->($args)/100);
-#      },
-#      old => sub { '' },
-#      _format =>
-#      sub {
-#        my ($value, $fmt) = @_;
-#        if ($fmt =~ /^m(\d+)/) {
-#       return sprintf("%$1s", sprintf("%.2f", $value/100));
-#        }
-#        elsif ($fmt =~ /%/) {
-#       return sprintf($fmt, $value);
-#        }
-#      },
-#      iterate_options_reset => sub { $option_index = -1 },
-#      iterate_options => sub { ++$option_index < @options },
-#      option => sub { CGI::escapeHTML($options[$option_index]{$_[0]}) },
-#      ifOptions => sub { @options },
-#      options => sub { nice_options(@options) },
-#     );
-#   # this should be reset once the order has been paid
-#   $session{orderPayment} = $order->{id};
-  
-#   page('checkoutcard.tmpl', \%acts);
-# }
-
 sub tag_ifPayment {
   my ($payment, $types_by_name, $args) = @_;
 
@@ -702,8 +508,11 @@ sub purchase {
   defined $ccNumber or $ccNumber = '';
   my $ccExpiry = param('cardExpiry');
   defined $ccExpiry or $ccExpiry = '';
-  $order{affiliate_code} = defined $session{affiliate_code} ?
-    $session{affiliate_code} : '';
+  my $affiliate_code = $session{affiliate_code};
+  defined $affiliate_code && length $affiliate_code
+    or $affiliate_code = param('affiliate_code');
+  defined $affiliate_code or $affiliate_code = '';
+  $order{affiliate_code} = $affiliate_code;
 
   use Digest::MD5 'md5_hex';
   $ccNumber =~ tr/0-9//cd;
@@ -762,9 +571,11 @@ sub purchase {
   my $user = get_siteuser(\%session, $cfg, $CGI::Q);
   if ($user) {
     $order{userId} = $user->{userId};
+    $order{siteuser_id} = $user->{id};
   }
   else {
     $order{userId} = '';
+    $order{siteuser_id} = -1;
   }
 
   # this should be hard to guess
index 4c7f937..b15fddd 100644 (file)
@@ -10,6 +10,52 @@ Maybe I'll add some other bits here.
 
 =head1 CHANGES
 
+=head2 0.14_26
+
+=over
+
+=item *
+
+the referer checks for affiliate.pl extracted the Referer header
+domain incorrectly.
+
+=item *
+
+the order affiliate_code is now accepted as a CGI parameter during
+purchase if it isn't set in the session.
+
+=item *
+
+the order siteuser_id field wasn't being set
+
+=item *
+
+added an affiliate_name column to the siteusers table.  This value is
+required to be unique if non-empty and may only contain alphanumeric
+characters.  You will need to add this to any custom templates.
+
+=item *
+
+affiliate.pl now accepts alternatives to the id parameter:
+
+=over
+
+=item *
+
+lo - the logon name of the user
+
+=item *
+
+co - the affiliate name of the user
+
+=back
+
+=item *
+
+some prep work for site user images
+
+=back
+
 =head2 0.14_25
 
 =over
index fbd7549..a431cdd 100644 (file)
             </td>
             <td bgcolor="#FFFFFF"><:help editsiteuser billEmail:>  <:error_img billEmail:></td>
           </tr>
+          <tr> 
+            <th bgcolor="#FFFFFF" align="left">Affiliate Name: </th>
+            <td bgcolor="#FFFFFF"> 
+              <input type="text" name="affiliate_name" value="<:old affiliate_name siteuser affiliate_name:>" />
+            </td>
+            <td bgcolor="#FFFFFF"><:help editsiteuser affiliate_name:>  <:error_img affiliate_name:></td>
+          </tr>
           <tr> 
             <th bgcolor="#FFFFFF" align="left" valign="top">Admin Notes: </th>
             <td bgcolor="#FFFFFF"> 
index 1cc0792..1a5ebd8 100644 (file)
           <input type="text" name="facsimile" value="<:last facsimile:>" size="32" maxlength="80" /><:error_img facsimile:>
         </td>
       </tr>
+<:ifCfg affiliate prompt_name 0:>
+      <tr> 
+        <th nowrap="nowrap" align="left"><b><font face="Verdana, Arial, Helvetica, sans-serif" size="-2">Affiliate Name:</font></b></th>
+        <td width="100%" nowrap="nowrap"> 
+          <input type="text" name="affiliate_name" value="<:last affiliate_name:>" size="40" maxlength="40" /><:error_img affiliate_name:>
+        </td>
+      </tr>
+<:or:><:eif:>
 <:if Cfg "site users" billing_on_main_opts 1:>
       <tr> 
         <td colspan="2" height="20"><br>
index 041f6bd..3982a6f 100644 (file)
--- a/test.cfg
+++ b/test.cfg
@@ -59,6 +59,8 @@ payment type names.11=FaxProForma
 payment type names.12=EmailProForma
 payment type required.11=facsimile
 
+affiliate.prompt_name=1
+
 dealer.bsb=999999
 dealer.accountno=77777777
 shop.display_facsimile=Fax Number