Merge branch 'master' of git.freeside.biz:/home/git/freeside
[freeside.git] / FS / FS / Conf.pm
index 5488806..42fe9ec 100644 (file)
@@ -5,6 +5,7 @@ use Carp;
 use IO::File;
 use File::Basename;
 use MIME::Base64;
+use Locale::Currency;
 use FS::ConfItem;
 use FS::ConfDefaults;
 use FS::Conf_compat17;
@@ -13,6 +14,7 @@ use FS::payby;
 use FS::conf;
 use FS::Record qw(qsearch qsearchs);
 use FS::UID qw(dbh datasrc use_confcompat);
+use FS::Misc::Invoicing qw( spool_formats );
 
 $base_dir = '%%%FREESIDE_CONF%%%';
 
@@ -182,7 +184,7 @@ sub exists {
   my $self = shift;
   return $self->_usecompat('exists', @_) if use_confcompat;
 
-  my($name, $agentnum)=@_;
+  #my($name, $agentnum)=@_;
 
   carp "FS::Conf->exists(". join(', ', @_). ") called"
     if $DEBUG > 1;
@@ -190,6 +192,54 @@ sub exists {
   defined($self->_config(@_));
 }
 
+#maybe this should just be the new exists instead of getting a method of its
+#own, but i wanted to avoid possible fallout
+
+sub config_bool {
+  my $self = shift;
+  return $self->_usecompat('exists', @_) if use_confcompat;
+
+  my($name,$agentnum,$agentonly) = @_;
+
+  carp "FS::Conf->config_bool(". join(', ', @_). ") called"
+    if $DEBUG > 1;
+
+  #defined($self->_config(@_));
+
+  #false laziness w/_config
+  my $hashref = { 'name' => $name };
+  local $FS::Record::conf = undef;  # XXX evil hack prevents recursion
+  my $cv;
+  my @a = (
+    ($agentnum || ()),
+    ($agentonly && $agentnum ? () : '')
+  );
+  my @l = (
+    ($self->{locale} || ()),
+    ($self->{localeonly} && $self->{locale} ? () : '')
+  );
+  # try with the agentnum first, then fall back to no agentnum if allowed
+  foreach my $a (@a) {
+    $hashref->{agentnum} = $a;
+    foreach my $l (@l) {
+      $hashref->{locale} = $l;
+      $cv = FS::Record::qsearchs('conf', $hashref);
+      if ( $cv ) {
+        if ( $cv->value eq '0'
+               && ($hashref->{agentnum} || $hashref->{locale} )
+           ) 
+        {
+          return 0; #an explicit false override, don't continue looking
+        } else {
+          return 1;
+        }
+      }
+    }
+  }
+  return 0;
+
+}
+
 =item config_orbase KEY SUFFIX
 
 Returns the configuration value or values (depending on context) for 
@@ -268,8 +318,13 @@ sub touch {
   return $self->_usecompat('touch', @_) if use_confcompat;
 
   my($name, $agentnum) = @_;
-  unless ( $self->exists($name, $agentnum) ) {
-    $self->set($name, '', $agentnum);
+  #unless ( $self->exists($name, $agentnum) ) {
+  unless ( $self->config_bool($name, $agentnum) ) {
+    if ( $agentnum && $self->exists($name) && $self->config($name,$agentnum) eq '0' ) {
+      $self->delete($name, $agentnum);
+    } else {
+      $self->set($name, '', $agentnum);
+    }
   }
 }
 
@@ -356,6 +411,31 @@ sub delete {
   }
 }
 
+#maybe this should just be the new delete instead of getting a method of its
+#own, but i wanted to avoid possible fallout
+
+sub delete_bool {
+  my $self = shift;
+  return $self->_usecompat('delete', @_) if use_confcompat;
+
+  my($name, $agentnum) = @_;
+
+  warn "[FS::Conf] DELETE $name\n" if $DEBUG;
+
+  my $cv = FS::Record::qsearchs('conf', { name     => $name,
+                                          agentnum => $agentnum,
+                                          locale   => $self->{locale},
+                                        });
+
+  if ( $cv ) {
+    my $error = $cv->delete;
+    die $error if $error;
+  } elsif ( $agentnum ) {
+    $self->set($name, '0', $agentnum);
+  }
+
+}
+
 =item import_config_item CONFITEM DIR 
 
   Imports the item specified by the CONFITEM (see L<FS::ConfItem>) into
@@ -610,12 +690,6 @@ my %msg_template_options = (
   'per_agent' => 1,
 );
 
-my $_gateway_name = sub {
-  my $g = shift;
-  return '' if !$g;
-  ($g->gateway_username . '@' . $g->gateway_module);
-};
-
 my %payment_gateway_options = (
   'type'        => 'select-sub',
   'options_sub' => sub {
@@ -623,14 +697,54 @@ my %payment_gateway_options = (
         'table' => 'payment_gateway',
         'hashref' => { 'disabled' => '' },
       });
-    map { $_->gatewaynum, $_gateway_name->($_) } @gateways;
+    map { $_->gatewaynum, $_->label } @gateways;
   },
   'option_sub'  => sub {
     my $gateway = FS::payment_gateway->by_key(shift);
-    $_gateway_name->($gateway);
+    $gateway ? $gateway->label : ''
+  },
+);
+
+my %batch_gateway_options = (
+  %payment_gateway_options,
+  'options_sub' => sub {
+    my @gateways = qsearch('payment_gateway',
+      {
+        'disabled'          => '',
+        'gateway_namespace' => 'Business::BatchPayment',
+      }
+    );
+    map { $_->gatewaynum, $_->label } @gateways;
   },
 );
 
+my @cdr_formats = (
+  '' => '',
+  'default' => 'Default',
+  'source_default' => 'Default with source',
+  'accountcode_default' => 'Default plus accountcode',
+  'description_default' => 'Default with description field as destination',
+  'basic' => 'Basic',
+  'simple' => 'Simple',
+  'simple2' => 'Simple with source',
+  'accountcode_simple' => 'Simple with accountcode',
+);
+
+# takes the reason class (C, R, S) as an argument
+sub reason_type_options {
+  my $reason_class = shift;
+
+  'type'        => 'select-sub',
+  'options_sub' => sub {
+    map { $_->typenum => $_->type } 
+      qsearch('reason_type', { class => $reason_class });
+  },
+  'option_sub'  => sub {
+    my $type = FS::reason_type->by_key(shift);
+    $type ? $type->type : '';
+  }
+}
+
 #Billing (81 items)
 #Invoicing (50 items)
 #UI (69 items)
@@ -648,6 +762,15 @@ my %payment_gateway_options = (
   },
 
   {
+    'key'         => 'event_log_level',
+    'section'     => 'notification',
+    'description' => 'Store events in the internal log if they are at least this severe.  "info" is the default, "debug" is very detailed and noisy.',
+    'type'        => 'select',
+    'select_enum' => [ '', 'debug', 'info', 'notice', 'warning', 'error', ],
+    # don't bother with higher levels
+  },
+
+  {
     'key'         => 'log_sent_mail',
     'section'     => 'notification',
     'description' => 'Enable logging of template-generated email.',
@@ -678,6 +801,13 @@ my %payment_gateway_options = (
   },
 
   {
+    'key'         => 'part_pkg-lineage',
+    'section'     => '',
+    'description' => 'When editing a package definition, if setup or recur fees are changed, create a new package rather than changing the existing package.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'apacheip',
     #not actually deprecated yet
     #'section'     => 'deprecated',
@@ -730,6 +860,20 @@ my %payment_gateway_options = (
   },
 
   {
+    'key'         => 'cust_main-select-prorate_day',
+    'section'     => 'billing',
+    'description' => 'When used with prorate or anniversary packages, allows the selection of the prorate day of month, on a per-customer basis',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'anniversary-rollback',
+    'section'     => 'billing',
+    'description' => 'When billing an anniversary package ordered after the 28th, roll the anniversary date back to the 28th instead of forward into the following month.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'encryption',
     'section'     => 'billing',
     'description' => 'Enable encryption of credit cards and echeck numbers',
@@ -861,6 +1005,34 @@ my %payment_gateway_options = (
   },
 
   {
+    'key'         => 'currency',
+    'section'     => 'billing',
+    'description' => 'Main accounting currency',
+    'type'        => 'select',
+    'select_enum' => [ '', qw( USD AUD CAD DKK EUR GBP ILS JPY NZD XAF ) ],
+  },
+
+  {
+    'key'         => 'currencies',
+    'section'     => 'billing',
+    'description' => 'Additional accepted currencies',
+    'type'        => 'select-sub',
+    'multiple'    => 1,
+    'options_sub' => sub { 
+                           map { $_ => code2currency($_) } all_currency_codes();
+                        },
+    'sort_sub'    => sub ($$) { $_[0] cmp $_[1]; },
+    'option_sub'  => sub { code2currency(shift); },
+  },
+
+  {
+    'key'         => 'business-batchpayment-test_transaction',
+    'section'     => 'billing',
+    'description' => 'Turns on the Business::BatchPayment test_mode flag.  Note that not all gateway modules support this flag; if yours does not, using the batch gateway will fail.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'countrydefault',
     'section'     => 'UI',
     'description' => 'Default two-letter country code (if not supplied, the default is `US\')',
@@ -887,31 +1059,20 @@ my %payment_gateway_options = (
     'select_hash' => [
                        '%b %o, %Y' => 'Mon DDth, YYYY',
                        '%e %b %Y'  => 'DD Mon YYYY',
+                       '%m/%d/%Y'  => 'MM/DD/YYYY',
+                       '%d/%m/%Y'  => 'DD/MM/YYYY',
+                      '%Y/%m/%d'  => 'YYYY/MM/DD',
                      ],
   },
 
   {
-    'key'         => 'deletecustomers',
-    'section'     => 'UI',
-    'description' => 'Enable customer deletions.  Be very careful!  Deleting a customer will remove all traces that the customer ever existed!  It should probably only be used when auditing a legacy database.  Normally, you cancel all of a customers\' packages if they cancel service.',
-    'type'        => 'checkbox',
-  },
-
-  {
     'key'         => 'deleteinvoices',
     'section'     => 'UI',
-    'description' => 'Enable invoices deletions.  Be very careful!  Deleting an invoice will remove all traces that the invoice ever existed!  Normally, you would apply a credit against the invoice instead.',  #invoice voiding?
+    'description' => 'Enable invoices deletions.  Be very careful!  Deleting an invoice will remove all traces that the invoice ever existed!  Normally, you would void or apply a credit against the invoice instead.',
     'type'        => 'checkbox',
   },
 
   {
-    'key'         => 'deletepayments',
-    'section'     => 'billing',
-    'description' => 'Enable deletion of unclosed payments.  Really, with voids this is pretty much not recommended in any situation anymore.  Be very careful!  Only delete payments that were data-entry errors, not adjustments.  Optionally specify one or more comma-separated email addresses to be notified when a payment is deleted.',
-    'type'        => [qw( checkbox text )],
-  },
-
-  {
     'key'         => 'deletecredits',
     #not actually deprecated yet
     #'section'     => 'deprecated',
@@ -1013,6 +1174,13 @@ my %payment_gateway_options = (
   },
 
   {
+    'key'         => 'svc_acct-ip_addr',
+    'section'     => '',
+    'description' => 'Enable IP address management on login services like for broadband services.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'exclude_ip_addr',
     'section'     => '',
     'description' => 'Exclude these from the list of available broadband service IP addresses. (One per line)',
@@ -1081,7 +1249,15 @@ my %payment_gateway_options = (
   {
     'key'         => 'invoice_html',
     'section'     => 'invoicing',
-    'description' => 'Optional HTML template for invoices.  See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:2.1:Documentation:Administration#HTML_invoice_templates">billing documentation</a> for details.',
+    'description' => 'HTML template for invoices.  See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:2.1:Documentation:Administration#HTML_invoice_templates">billing documentation</a> for details.',
+
+    'type'        => 'textarea',
+  },
+
+  {
+    'key'         => 'quotation_html',
+    'section'     => '',
+    'description' => 'HTML template for quotations.',
 
     'type'        => 'textarea',
   },
@@ -1129,6 +1305,13 @@ my %payment_gateway_options = (
   },
 
   {
+    'key'         => 'quotation_latex',
+    'section'     => '',
+    'description' => 'LaTeX template for typeset PostScript quotations.',
+    'type'        => 'textarea',
+  },
+
+  {
     'key'         => 'invoice_latextopmargin',
     'section'     => 'invoicing',
     'description' => 'Optional LaTeX invoice topmargin setting. Include units.',
@@ -1187,6 +1370,15 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'quotation_latexnotes',
+    'section'     => '',
+    'description' => 'Notes section for LaTeX typeset PostScript quotations.',
+    'type'        => 'textarea',
+    'per_agent'   => 1,
+    'per_locale'  => 1,
+  },
+
+  {
     'key'         => 'invoice_latexfooter',
     'section'     => 'invoicing',
     'description' => 'Footer for LaTeX typeset PostScript invoices.',
@@ -1216,7 +1408,7 @@ and customer address. Include units.',
   {
     'key'         => 'invoice_latexextracouponspace',
     'section'     => 'invoicing',
-    'description' => 'Optional LaTeX invoice textheight space to reserve for a tear off coupon. Include units.',
+    'description' => 'Optional LaTeX invoice textheight space to reserve for a tear off coupon.  Include units.  Default is 3.6cm',
     'type'        => 'text',
     'per_agent'   => 1,
     'validate'    => sub { shift =~
@@ -1325,7 +1517,7 @@ and customer address. Include units.',
     'section'     => 'invoicing',
     'description' => 'Optional default invoice term, used to calculate a due date printed on invoices.',
     'type'        => 'select',
-    'select_enum' => [ '', 'Payable upon receipt', 'Net 0', 'Net 3', 'Net 9', 'Net 10', 'Net 15', 'Net 20', 'Net 21', 'Net 30', 'Net 45', 'Net 60', 'Net 90' ],
+    'select_enum' => [ '', 'Payable upon receipt', 'Net 0', 'Net 3', 'Net 9', 'Net 10', 'Net 15', 'Net 18', 'Net 20', 'Net 21', 'Net 30', 'Net 45', 'Net 60', 'Net 90' ],
   },
 
   { 
@@ -1347,8 +1539,18 @@ and customer address. Include units.',
     'section'     => 'invoicing',
     'description' => 'Split invoice into sections and label according to package category when enabled.',
     'type'        => 'checkbox',
+    'per_agent'   => 1,
   },
 
+  #quotations seem broken-ish with sections ATM?
+  #{ 
+  #  'key'         => 'quotation_sections',
+  #  'section'     => 'invoicing',
+  #  'description' => 'Split quotations into sections and label according to package category when enabled.',
+  #  'type'        => 'checkbox',
+  #  'per_agent'   => 1,
+  #},
+
   { 
     'key'         => 'usage_class_as_a_section',
     'section'     => 'invoicing',
@@ -1397,6 +1599,7 @@ and customer address. Include units.',
     'description' => 'Send payment receipts.',
     'type'        => 'checkbox',
     'per_agent'   => 1,
+    'agent_bool'  => 1,
   },
 
   {
@@ -1445,6 +1648,7 @@ and customer address. Include units.',
     'section'     => 'required',
     'description' => 'Print command for paper invoices, for example `lpr -h\'',
     'type'        => 'text',
+    'per_agent'   => 1,
   },
 
   {
@@ -1571,6 +1775,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'disable_maxselect',
+    'section'     => 'UI',
+    'description' => 'Prevent changing the number of records per page.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'session-start',
     'section'     => 'session',
     'description' => 'If defined, the command which is executed on the Freeside machine when a session begins.  The contents of the file are treated as a double-quoted perl string, with the following variables available: <code>$ip</code>, <code>$nasip</code> and <code>$nasfqdn</code>, which are the IP address of the starting session, and the IP address and fully-qualified domain name of the NAS this session is on.',
@@ -1770,6 +1981,7 @@ and customer address. Include units.',
     'section'     => 'username',
     'description' => 'Allow uppercase characters in usernames.  Not recommended for use with FreeRADIUS with MySQL backend, which is case-insensitive by default.',
     'type'        => 'checkbox',
+    'per_agent'   => 1,
   },
 
   { 
@@ -1815,6 +2027,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'unmask_ss',
+    'section'     => 'UI',
+    'description' => "Don't mask social security numbers in the web interface.",
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'show_stateid',
     'section'     => 'UI',
     'description' => "Turns on display/collection of driver's license/state issued id numbers in the web interface.  Sometimes required by electronic check (ACH) processors.",
@@ -1822,6 +2041,14 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'national_id-country',
+    'section'     => 'UI',
+    'description' => 'Track a national identification number, for specific countries.',
+    'type'        => 'select',
+    'select_enum' => [ '', 'MY' ],
+  },
+
+  {
     'key'         => 'show_bankstate',
     'section'     => 'UI',
     'description' => "Turns on display/collection of state for bank accounts in the web interface.  Sometimes required by electronic check (ACH) processors.",
@@ -1867,7 +2094,7 @@ and customer address. Include units.',
     'key'         => 'locale',
     'section'     => 'UI',
     'description' => 'Default locale',
-    'type'        => 'select',
+    'type'        => 'select-sub',
     'options_sub' => sub {
       map { $_ => FS::Locales->description($_) } FS::Locales->locales;
     },
@@ -1881,7 +2108,7 @@ and customer address. Include units.',
     'section'     => 'self-service',
     'description' => 'Acceptable payment types for the signup server',
     'type'        => 'selectmultiple',
-    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB PREPAY BILL COMP) ],
+    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB PREPAY PPAL BILL COMP) ],
   },
 
   {
@@ -1942,11 +2169,18 @@ and customer address. Include units.',
   {
     'key'         => 'signup_server-default_svcpart',
     'section'     => 'self-service',
-    'description' => 'Default service definition for the signup server - only necessary for services that trigger special provisioning widgets (such as DID provisioning).',
+    'description' => 'Default service definition for the signup server - only necessary for services that trigger special provisioning widgets (such as DID provisioning or domain selection).',
     'type'        => 'select-part_svc',
   },
 
   {
+    'key'         => 'signup_server-default_domsvc',
+    'section'     => 'self-service',
+    'description' => 'If specified, the default domain svcpart for signup (useful when domain is set to selectable choice).',
+    'type'        => 'text',
+  },
+
+  {
     'key'         => 'signup_server-mac_addr_svcparts',
     'section'     => 'self-service',
     'description' => 'Service definitions which can receive mac addresses (current mapped to username for svc_acct).',
@@ -1981,6 +2215,14 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'signup_server-terms_of_service',
+    'section'     => 'self-service',
+    'description' => 'Terms of Service for the signup server.  May contain HTML.',
+    'type'        => 'textarea',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'selfservice_server-base_url',
     'section'     => 'self-service',
     'description' => 'Base URL for the self-service web interface - necessary for some widgets to find their way, including retrieval of non-US state information and phone number provisioning.',
@@ -2030,6 +2272,12 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice-timeout',
+    'section'     => 'self-service',
+    'description' => 'Timeout for the self-service login cookie, in seconds.  Defaults to 1 hour.',
+  },
+
+  {
     'key'         => 'backend-realtime',
     'section'     => 'billing',
     'description' => 'Run billing for backend signups immediately.',
@@ -2247,7 +2495,7 @@ and customer address. Include units.',
     'section'     => 'billing',
     'description' => 'Available payment types.',
     'type'        => 'selectmultiple',
-    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP) ],
+    'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD PPAL COMP) ],
   },
 
   {
@@ -2255,7 +2503,14 @@ and customer address. Include units.',
     'section'     => 'UI',
     'description' => 'Default payment type.  HIDE disables display of billing information and sets customers to BILL.',
     'type'        => 'select',
-    'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP HIDE) ],
+    'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD PPAL COMP HIDE) ],
+  },
+
+  {
+    'key'         => 'require_cash_deposit_info',
+    'section'     => 'billing',
+    'description' => 'When recording cash payments, display bank deposit information fields.',
+    'type'        => 'checkbox',
   },
 
   {
@@ -2297,6 +2552,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'svc_broadband-radius',
+    'section'     => '',
+    'description' => 'Enable RADIUS groups for broadband services.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'svc_acct-alldomains',
     'section'     => '',
     'description' => 'Allow accounts to select any domain in the database.  Normally accounts can only select from the domain set in the service definition and those purchased by the customer.',
@@ -2360,8 +2622,9 @@ and customer address. Include units.',
   {
     'key'         => 'manual_process-pkgpart',
     'section'     => 'billing',
-    'description' => 'Package to add to each manual credit card and ACH payments entered from the backend.  Enabling this option may be in violation of your merchant agreement(s), so please check them carefully before enabling this option.',
+    'description' => 'Package to add to each manual credit card and ACH payment entered by employees from the backend.  Enabling this option may be in violation of your merchant agreement(s), so please check it(/them) carefully before enabling this option.',
     'type'        => 'select-part_pkg',
+    'per_agent'   => 1,
   },
 
   {
@@ -2383,6 +2646,57 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice_process-pkgpart',
+    'section'     => 'billing',
+    'description' => 'Package to add to each manual credit card and ACH payment entered by the customer themselves in the self-service interface.  Enabling this option may be in violation of your merchant agreement(s), so please check it(/them) carefully before enabling this option.',
+    'type'        => 'select-part_pkg',
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'selfservice_process-display',
+    'section'     => 'billing',
+    'description' => 'When using selfservice_process-pkgpart, add the fee to the amount entered (default), or subtract the fee from the amount entered.',
+    'type'        => 'select',
+    'select_hash' => [
+                       'add'      => 'Add fee to amount entered',
+                       'subtract' => 'Subtract fee from amount entered',
+                     ],
+  },
+
+  {
+    'key'         => 'selfservice_process-skip_first',
+    'section'     => 'billing',
+    'description' => "When using selfservice_process-pkgpart, omit the fee if it is the customer's first payment.",
+    'type'        => 'checkbox',
+  },
+
+#  {
+#    'key'         => 'auto_process-pkgpart',
+#    'section'     => 'billing',
+#    'description' => 'Package to add to each automatic credit card and ACH payment processed by billing events.  Enabling this option may be in violation of your merchant agreement(s), so please check them carefully before enabling this option.',
+#    'type'        => 'select-part_pkg',
+#  },
+#
+##  {
+##    'key'         => 'auto_process-display',
+##    'section'     => 'billing',
+##    'description' => 'When using auto_process-pkgpart, add the fee to the amount entered (default), or subtract the fee from the amount entered.',
+##    'type'        => 'select',
+##    'select_hash' => [
+##                       'add'      => 'Add fee to amount entered',
+##                       'subtract' => 'Subtract fee from amount entered',
+##                     ],
+##  },
+#
+#  {
+#    'key'         => 'auto_process-skip_first',
+#    'section'     => 'billing',
+#    'description' => "When using auto_process-pkgpart, omit the fee if it is the customer's first payment.",
+#    'type'        => 'checkbox',
+#  },
+
+  {
     'key'         => 'allow_negative_charges',
     'section'     => 'billing',
     'description' => 'Allow negative charges.  Normally not used unless importing data from a legacy system that requires this.',
@@ -2468,6 +2782,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice-svc_forward_svcpart',
+    'section'     => 'self-service',
+    'description' => 'Service for self-service forward editing.',
+    'type'        => 'select-part_svc',
+  },
+
+  {
     'key'         => 'selfservice-password_reset_verification',
     'section'     => 'self-service',
     'description' => 'If enabled, specifies the type of verification required for self-service password resets.',
@@ -2476,7 +2797,21 @@ and customer address. Include units.',
                        'paymask,amount,zip' => 'Verify with credit card (or bank account) last 4 digits, payment amount and zip code',
                      ],
   },
-  
+
+  {
+    'key'         => 'selfservice-password_reset_msgnum',
+    'section'     => 'self-service',
+    'description' => 'Template to use for password reset emails.',
+    %msg_template_options,
+  },
+
+  {
+    'key'         => 'selfservice-hide_invoices-taxclass',
+    'section'     => 'self-service',
+    'description' => 'Hide invoices with only this package tax class from self-service and supress sending (emailing, printing, faxing) them.  Typically set to something like "Previous balance" and used when importing legacy invoices into legacy_cust_bill.',
+    'type'        => 'text',
+  },
+
   {
     'key'         => 'selfservice-recent-did-age',
     'section'     => 'self-service',
@@ -2622,14 +2957,28 @@ and customer address. Include units.',
 
   {
     'key'         => 'network_monitoring_system',
-    'section'     => '',
+    'section'     => 'network_monitoring',
     'description' => 'Networking monitoring system (NMS) integration.  <b>Torrus_Internal</b> uses the built-in Torrus ticketing system (see the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:2.1:Documentation:Torrus_Installation">integrated networking monitoring system installation instructions</a>).',
     'type'        => 'select',
-    #'select_enum' => [ '', qw(RT_Internal RT_Libs RT_External) ],
     'select_enum' => [ '', qw(Torrus_Internal) ],
   },
 
   {
+    'key'         => 'nms-auto_add-svc_ips',
+    'section'     => 'network_monitoring',
+    'description' => 'Automatically add (and remove) IP addresses from these service tables to the network monitoring system.',
+    'type'        => 'selectmultiple',
+    'select_enum' => [ 'svc_acct', 'svc_broadband', 'svc_dsl' ],
+  },
+
+  {
+    'key'         => 'nms-auto_add-community',
+    'section'     => 'network_monitoring',
+    'description' => 'SNMP community string to use when automatically adding IP addresses from these services to the network monitoring system.',
+    'type'        => 'text',
+  },
+
+  {
     'key'         => 'ticket_system-default_queueid',
     'section'     => 'ticketing',
     'description' => 'Default queue used when creating new customer tickets.',
@@ -2769,6 +3118,14 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'company_url',
+    'section'     => 'UI',
+    'description' => 'Your company URL',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'company_address',
     'section'     => 'required',
     'description' => 'Your company address',
@@ -2831,6 +3188,7 @@ and customer address. Include units.',
     'section'     => '',
     'description' => "Use the agent's master service address as the service address (only ship_address2 can be entered, if blank on the master address).  Useful for multi-tenant applications.",
     'type'        => 'checkbox',
+    'per_agent'   => 1,
   },
 
   { 'key'         => 'referral_credit',
@@ -2858,7 +3216,7 @@ and customer address. Include units.',
     'section'     => 'invoicing',
     'description' => 'Enable FTP of raw invoice data - format.',
     'type'        => 'select',
-    'select_enum' => [ '', 'default', 'billco', ],
+    'options'     => [ spool_formats() ],
   },
 
   {
@@ -2894,7 +3252,7 @@ and customer address. Include units.',
     'section'     => 'invoicing',
     'description' => 'Enable spooling of raw invoice data - format.',
     'type'        => 'select',
-    'select_enum' => [ '', 'default', 'billco', ],
+    'options'     => [ spool_formats() ],
   },
 
   {
@@ -2905,22 +3263,56 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'svc_acct-usage_suspend',
-    'section'     => 'billing',
-    'description' => 'Suspends the package an account belongs to when svc_acct.seconds or a bytecount is decremented to 0 or below (accounts with an empty seconds and up|down|totalbytes value are ignored).  Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
-    'type'        => 'checkbox',
+    'key'         => 'bridgestone-batch_counter',
+    'section'     => '',
+    'description' => 'Batch counter for spool files.  Increments every time a spool file is uploaded.',
+    'type'        => 'text',
+    'per_agent'   => 1,
   },
 
   {
-    'key'         => 'svc_acct-usage_unsuspend',
-    'section'     => 'billing',
-    'description' => 'Unuspends the package an account belongs to when svc_acct.seconds or a bytecount is incremented from 0 or below to a positive value (accounts with an empty seconds and up|down|totalbytes value are ignored).  Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
-    'type'        => 'checkbox',
+    'key'         => 'bridgestone-prefix',
+    'section'     => '',
+    'description' => 'Agent identifier for uploading to BABT printing service.',
+    'type'        => 'text',
+    'per_agent'   => 1,
   },
 
   {
-    'key'         => 'svc_acct-usage_threshold',
-    'section'     => 'billing',
+    'key'         => 'bridgestone-confirm_template',
+    'section'     => '',
+    'description' => 'Confirmation email template for uploading to BABT service.  Text::Template format, with variables "$zipfile" (name of the zipped file), "$seq" (sequence number), "$prefix" (user ID string), and "$rows" (number of records in the file).  Should include Subject: and To: headers, separated from the rest of the message by a blank line.',
+    # this could use a true message template, but it's hard to see how that
+    # would make the world a better place
+    'type'        => 'textarea',
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'ics-confirm_template',
+    'section'     => '',
+    'description' => 'Confirmation email template for uploading to ICS invoice printing.  Text::Template format, with variables "%count" and "%sum".',
+    'type'        => 'textarea',
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'svc_acct-usage_suspend',
+    'section'     => 'billing',
+    'description' => 'Suspends the package an account belongs to when svc_acct.seconds or a bytecount is decremented to 0 or below (accounts with an empty seconds and up|down|totalbytes value are ignored).  Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'svc_acct-usage_unsuspend',
+    'section'     => 'billing',
+    'description' => 'Unuspends the package an account belongs to when svc_acct.seconds or a bytecount is incremented from 0 or below to a positive value (accounts with an empty seconds and up|down|totalbytes value are ignored).  Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'svc_acct-usage_threshold',
+    'section'     => 'billing',
     'description' => 'The threshold (expressed as percentage) of acct.seconds or acct.up|down|totalbytes at which a warning message is sent to a service holder.  Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
     'type'        => 'text',
   },
@@ -2955,6 +3347,16 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'cust_location-label_prefix',
+    'section'     => 'UI',
+    'description' => 'Optional "site ID" to show in the location label',
+    'type'        => 'select',
+    'select_hash' => [ '' => '',
+                       'CoStAg' => 'CoStAgXXXXX (country, state, agent name, locationnum)',
+                      ],
+  },
+
+  {
     'key'         => 'cust_pkg-display_times',
     'section'     => 'UI',
     'description' => 'Display full timestamps (not just dates) for customer packages.  Useful if you are doing real-time things like hourly prepaid.',
@@ -2978,7 +3380,7 @@ and customer address. Include units.',
   {
     'key'         => 'cust_pkg-show_fcc_voice_grade_equivalent',
     'section'     => 'UI',
-    'description' => "Show a field on package definitions for assigning a DS0 equivalency number suitable for use on FCC form 477.",
+    'description' => "Show fields on package definitions for FCC Form 477 classification",
     'type'        => 'checkbox',
   },
 
@@ -3018,10 +3420,14 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'echeck-nonus',
+    'key'         => 'echeck-country',
     'section'     => 'billing',
-    'description' => 'Disable ABA-format account checking for Electronic Check payment info',
-    'type'        => 'checkbox',
+    'description' => 'Format electronic check information for the specified country.',
+    'type'        => 'select',
+    'select_hash' => [ 'US' => 'United States',
+                       'CA' => 'Canada (enables branch)',
+                       'XX' => 'Other',
+                     ],
   },
 
   {
@@ -3104,7 +3510,7 @@ and customer address. Include units.',
   {
     'key'         => 'invoice-unitprice',
     'section'     => 'invoicing',
-    'description' => 'Enable unit pricing on invoices.',
+    'description' => 'Enable unit pricing on invoices and quantities on packages.',
     'type'        => 'checkbox',
   },
 
@@ -3133,7 +3539,7 @@ and customer address. Include units.',
   {
     'key'         => 'postal_invoice-recurring_only',
     'section'     => 'billing',
-    'description' => 'The postal invoice fee is omitted on invoices without reucrring charges when this is set.',
+    'description' => 'The postal invoice fee is omitted on invoices without recurring charges when this is set.',
     'type'        => 'checkbox',
   },
 
@@ -3166,12 +3572,53 @@ and customer address. Include units.',
     'section'     => 'billing',
     'description' => 'Default format for batches.',
     'type'        => 'select',
-    'select_enum' => [ 'csv-td_canada_trust-merchant_pc_batch',
+    'select_enum' => [ 'NACHA', 'csv-td_canada_trust-merchant_pc_batch',
                        'csv-chase_canada-E-xactBatch', 'BoM', 'PAP',
                        'paymentech', 'ach-spiritone', 'RBC'
                     ]
   },
 
+  { 'key'         => 'batch-gateway-CARD',
+    'section'     => 'billing',
+    'description' => 'Business::BatchPayment gateway for credit card batches.',
+    %batch_gateway_options,
+  },
+
+  { 'key'         => 'batch-gateway-CHEK',
+    'section'     => 'billing', 
+    'description' => 'Business::BatchPayment gateway for check batches.',
+    %batch_gateway_options,
+  },
+
+  {
+    'key'         => 'batch-reconsider',
+    'section'     => 'billing',
+    'description' => 'Allow imported batch results to change the status of payments from previous imports.  Enable this only if your gateway is known to send both positive and negative results for the same batch.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'batch-auto_resolve_days',
+    'section'     => 'billing',
+    'description' => 'Automatically resolve payment batches this many days after they were first downloaded.',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'batch-auto_resolve_status',
+    'section'     => 'billing',
+    'description' => 'When automatically resolving payment batches, take this action for payments of unknown status.',
+    'type'        => 'select',
+    'select_enum' => [ 'approve', 'decline' ],
+  },
+
+  {
+    'key'         => 'batch-errors_to',
+    'section'     => 'billing',
+    'description' => 'Email errors when processing batches to this address.  If unspecified, batch processing will stop immediately on error.',
+    'type'        => 'text',
+  },
+
   #lists could be auto-generated from pay_batch info
   {
     'key'         => 'batch-fixed_format-CARD',
@@ -3187,9 +3634,9 @@ and customer address. Include units.',
     'section'     => 'billing',
     'description' => 'Fixed (unchangeable) format for electronic check batches.',
     'type'        => 'select',
-    'select_enum' => [ 'csv-td_canada_trust-merchant_pc_batch', 'BoM', 'PAP',
-                       'paymentech', 'ach-spiritone', 'RBC', 'td_eft1464',
-                       'eft_canada'
+    'select_enum' => [ 'NACHA', 'csv-td_canada_trust-merchant_pc_batch', 'BoM',
+                       'PAP', 'paymentech', 'ach-spiritone', 'RBC',
+                       'td_eft1464', 'eft_canada'
                      ]
   },
 
@@ -3224,7 +3671,7 @@ and customer address. Include units.',
   {
     'key'         => 'batchconfig-paymentech',
     'section'     => 'billing',
-    'description' => 'Configuration for Chase Paymentech batching, five lines: 1. BIN, 2. Terminal ID, 3. Merchant ID, 4. Username, 5. Password (for batch uploads)',
+    'description' => 'Configuration for Chase Paymentech batching, six lines: 1. BIN, 2. Terminal ID, 3. Merchant ID, 4. Username, 5. Password (for batch uploads), 6. Flag to send recurring indicator.',
     'type'        => 'textarea',
   },
 
@@ -3243,18 +3690,39 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'batch-manual_approval',
+    'key'         => 'batchconfig-eft_canada',
     'section'     => 'billing',
-    'description' => 'Allow manual batch closure, which will approve all payments that do not yet have a status.  This is not advised, but is needed for payment processors that provide a report of rejected rather than approved payments.',
-    'type'        => 'checkbox',
+    'description' => 'Configuration for EFT Canada batching, four lines: 1. SFTP username, 2. SFTP password, 3. Transaction code, 4. Number of days to delay process date.  If you are using separate per-agent batches (batch-spoolagent), you must set this option separately for each agent, as the global setting will be ignored.',
+    'type'        => 'textarea',
+    'per_agent'   => 1,
   },
 
   {
-    'key'         => 'batchconfig-eft_canada',
+    'key'         => 'batchconfig-nacha-destination',
     'section'     => 'billing',
-    'description' => 'Configuration for EFT Canada batching, four lines: 1. SFTP username, 2. SFTP password, 3. Transaction code, 4. Number of days to delay process date.',
-    'type'        => 'textarea',
-    'per_agent'   => 1,
+    'description' => 'Configuration for NACHA batching, Destination (9 digit transit routing number).',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'batchconfig-nacha-destination_name',
+    'section'     => 'billing',
+    'description' => 'Configuration for NACHA batching, Destination (Bank Name, up to 23 characters).',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'batchconfig-nacha-origin',
+    'section'     => 'billing',
+    'description' => 'Configuration for NACHA batching, Origin (your 10-digit company number, IRS tax ID recommended).',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'batch-manual_approval',
+    'section'     => 'billing',
+    'description' => 'Allow manual batch closure, which will approve all payments that do not yet have a status.  This is not advised unless needed for specific payment processors that provide a report of rejected rather than approved payments.',
+    'type'        => 'checkbox',
   },
 
   {
@@ -3322,23 +3790,23 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'cust_main-skeleton_tables',
-    'section'     => '',
-    'description' => 'Tables which will have skeleton records inserted into them for each customer.  Syntax for specifying tables is unfortunately a tricky perl data structure for now.',
-    'type'        => 'textarea',
+    'key'         => 'cust_main-enable_birthdate',
+    'section'     => 'UI',
+    'description' => 'Enable tracking of a birth date with each customer record',
+    'type'        => 'checkbox',
   },
 
   {
-    'key'         => 'cust_main-skeleton_custnum',
-    'section'     => '',
-    'description' => 'Customer number specifying the source data to copy into skeleton tables for new customers.',
-    'type'        => 'text',
+    'key'         => 'cust_main-enable_spouse_birthdate',
+    'section'     => 'UI',
+    'description' => 'Enable tracking of a spouse birth date with each customer record',
+    'type'        => 'checkbox',
   },
 
   {
-    'key'         => 'cust_main-enable_birthdate',
+    'key'         => 'cust_main-enable_anniversary_date',
     'section'     => 'UI',
-    'descritpion' => 'Enable tracking of a birth date with each customer record',
+    'description' => 'Enable tracking of an anniversary date with each customer record',
     'type'        => 'checkbox',
   },
 
@@ -3371,6 +3839,13 @@ and customer address. Include units.',
     'type'        => 'checkbox',
   },
 
+  {
+    'key'         => 'fuzzy-fuzziness',
+    'section'     => 'UI',
+    'description' => 'Set the "fuzziness" of fuzzy searching (see the String::Approx manpage for details).  Defaults to 10%',
+    'type'        => 'text',
+  },
+
   { 'key'         => 'pkg_referral',
     'section'     => '',
     'description' => 'Enable package-specific advertising sources.',
@@ -3490,6 +3965,39 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'cust_bill-line_item-date_style',
+    'section'     => 'billing',
+    'description' => 'Display format for line item date ranges on invoice line items.',
+    'type'        => 'select',
+    'select_hash' => [ ''           => 'STARTDATE-ENDDATE',
+                       'month_of'   => 'Month of MONTHNAME',
+                       'X_month'    => 'DATE_DESC MONTHNAME',
+                     ],
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'cust_bill-line_item-date_style-non_monthly',
+    'section'     => 'billing',
+    'description' => 'If set, override cust_bill-line_item-date_style for non-monthly charges.',
+    'type'        => 'select',
+    'select_hash' => [ ''           => 'Default',
+                       'start_end'  => 'STARTDATE-ENDDATE',
+                       'month_of'   => 'Month of MONTHNAME',
+                       'X_month'    => 'DATE_DESC MONTHNAME',
+                     ],
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'cust_bill-line_item-date_description',
+    'section'     => 'billing',
+    'description' => 'Text to display for "DATE_DESC" when using cust_bill-line_item-date_style DATE_DESC MONTHNAME.',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'support_packages',
     'section'     => '',
     'description' => 'A list of packages eligible for RT ticket time transfer, one pkgpart per line.', #this should really be a select multiple, or specified in the packages themselves...
@@ -3502,6 +4010,7 @@ and customer address. Include units.',
     'section'     => '',
     'description' => 'Require daytime or night phone for all customer records.',
     'type'        => 'checkbox',
+    'per_agent'   => 1,
   },
 
   {
@@ -3509,6 +4018,18 @@ and customer address. Include units.',
     'section'     => '',
     'description' => 'Email address field is required: require at least one invoicing email address for all customer records.',
     'type'        => 'checkbox',
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'cust_main-check_unique',
+    'section'     => '',
+    'description' => 'Warn before creating a customer record where these fields duplicate another customer.',
+    'type'        => 'select',
+    'multiple'    => 1,
+    'select_hash' => [ 
+      #'address1' => 'Billing address',
+    ],
   },
 
   {
@@ -3522,77 +4043,35 @@ and customer address. Include units.',
     'key'         => 'cancel_credit_type',
     'section'     => 'billing',
     'description' => 'The group to use for new, automatically generated credit reasons resulting from cancellation.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                          map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                        },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                          my $reason_type = FS::Record::qsearchs(
-                            'reason_type', { 'typenum' => shift }
-                          );
-                           $reason_type ? $reason_type->type : '';
-                        },
+    reason_type_options('R'),
+  },
+
+  {
+    'key'         => 'suspend_credit_type',
+    'section'     => 'billing',
+    'description' => 'The group to use for new, automatically generated credit reasons resulting from package suspension.',
+    reason_type_options('R'),
   },
 
   {
     'key'         => 'referral_credit_type',
     'section'     => 'deprecated',
     'description' => 'Used to be the group to use for new, automatically generated credit reasons resulting from referrals.  Now set in a package billing event for the referral.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                          map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                        },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                          my $reason_type = FS::Record::qsearchs(
-                            'reason_type', { 'typenum' => shift }
-                          );
-                           $reason_type ? $reason_type->type : '';
-                        },
+    reason_type_options('R'),
   },
 
   {
     'key'         => 'signup_credit_type',
     'section'     => 'billing', #self-service?
     'description' => 'The group to use for new, automatically generated credit reasons resulting from signup and self-service declines.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                          map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                        },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                          my $reason_type = FS::Record::qsearchs(
-                            'reason_type', { 'typenum' => shift }
-                          );
-                           $reason_type ? $reason_type->type : '';
-                        },
+    reason_type_options('R'),
   },
 
   {
     'key'         => 'prepayment_discounts-credit_type',
     'section'     => 'billing',
     'description' => 'Enables the offering of prepayment discounts and establishes the credit reason type.',
-    'type'        => 'select-sub',
-    'options_sub' => sub { require FS::Record;
-                           require FS::reason_type;
-                           map { $_->typenum => $_->type }
-                               FS::Record::qsearch('reason_type', { class=>'R' } );
-                         },
-    'option_sub'  => sub { require FS::Record;
-                           require FS::reason_type;
-                           my $reason_type = FS::Record::qsearchs(
-                             'reason_type', { 'typenum' => shift }
-                           );
-                           $reason_type ? $reason_type->type : '';
-                         },
-
+    reason_type_options('R'),
   },
 
   {
@@ -3601,9 +4080,9 @@ and customer address. Include units.',
     'description' => 'Enables searching of various formatted values in cust_main.agent_custid',
     'type'        => 'select',
     'select_hash' => [
-                       ''      => 'Numeric only',
-                       '\d{7}' => 'Numeric only, exactly 7 digits',
-                       'ww?d+' => 'Numeric with one or two letter prefix',
+                       ''       => 'Numeric only',
+                       '\d{7}'  => 'Numeric only, exactly 7 digits',
+                       'ww?d+'  => 'Numeric with one or two letter prefix',
                      ],
   },
 
@@ -3627,8 +4106,9 @@ and customer address. Include units.',
   {
     'key'         => 'disable_previous_balance',
     'section'     => 'invoicing',
-    'description' => 'Disable inclusion of previous balance, payment, and credit lines on invoices',
+    'description' => 'Disable inclusion of previous balance, payment, and credit lines on invoices.',
     'type'        => 'checkbox',
+    'per_agent'   => 1,
   },
 
   {
@@ -3653,6 +4133,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'previous_balance-show_on_statements',
+    'section'     => 'invoicing',
+    'description' => 'Show previous invoices on statements, without itemized charges.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'balance_due_below_line',
     'section'     => 'invoicing',
     'description' => 'Place the balance due message below a line.  Only meaningful when when invoice_sections is false.',
@@ -3660,6 +4147,24 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'always_show_tax',
+    'section'     => 'invoicing',
+    'description' => 'Show a line for tax on the invoice even when the tax is zero.  Optionally provide text for the tax name to show.',
+    'type'        => [ qw(checkbox text) ],
+  },
+
+  {
+    'key'         => 'address_standardize_method',
+    'section'     => 'UI', #???
+    'description' => 'Method for standardizing customer addresses.',
+    'type'        => 'select',
+    'select_hash' => [ '' => '', 
+                       'usps' => 'U.S. Postal Service',
+                       'ezlocate' => 'EZLocate',
+                     ],
+  },
+
+  {
     'key'         => 'usps_webtools-userid',
     'section'     => 'UI',
     'description' => 'Production UserID for USPS web tools.   Enables USPS address standardization.  See the <a href="http://www.usps.com/webtools/">USPS website</a>, register and agree not to use the tools for batch purposes.',
@@ -3674,6 +4179,20 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'ezlocate-userid',
+    'section'     => 'UI',
+    'description' => 'User ID for EZ-Locate service.  See <a href="http://www.geocode.com/">the TomTom website</a> for access and pricing information.',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'ezlocate-password',
+    'section'     => 'UI',
+    'description' => 'Password for EZ-Locate service.',
+    'type'        => 'text'
+  },
+
+  {
     'key'         => 'cust_main-auto_standardize_address',
     'section'     => 'UI',
     'description' => 'When using USPS web tools, automatically standardize the address without asking.',
@@ -3690,9 +4209,22 @@ and customer address. Include units.',
   {
     'key'         => 'census_year',
     'section'     => 'UI',
-    'description' => 'The year to use in census tract lookups',
+    'description' => 'The year to use in census tract lookups.  NOTE: you need to select 2012 for Year 2010 Census tract codes.  A selection of 2011 or 2010 provides Year 2000 Census tract codes.  Use the freeside-censustract-update tool if exisitng customers need to be changed.',
     'type'        => 'select',
-    'select_enum' => [ qw( 2010 2009 2008 ) ],
+    'select_enum' => [ qw( 2012 2011 2010 ) ],
+  },
+
+  {
+    'key'         => 'tax_district_method',
+    'section'     => 'UI',
+    'description' => 'The method to use to look up tax district codes.',
+    'type'        => 'select',
+    #'select_hash' => [ FS::Misc::Geo::get_district_methods() ],
+    #after RT#13763, using FS::Misc::Geo here now causes a dependancy loop :/
+    'select_hash' => [
+                       ''         => '',
+                       'wa_sales' => 'Washington sales tax',
+                     ],
   },
 
   {
@@ -3710,6 +4242,21 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'geocode_module',
+    'section'     => '',
+    'description' => 'Module to geocode (retrieve a latitude and longitude for) addresses',
+    'type'        => 'select',
+    'select_enum' => [ 'Geo::Coder::Googlev3' ],
+  },
+
+  {
+    'key'         => 'geocode-require_nw_coordinates',
+    'section'     => 'UI',
+    'description' => 'Require latitude and longitude in the North Western quadrant, e.g. for North American co-ordinates, etc.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'disable_acl_changes',
     'section'     => '',
     'description' => 'Disable all ACL changes, for demos.',
@@ -3762,6 +4309,31 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'cust_main-custnum-display_prefix',
+    'section'     => 'UI',
+    'description' => 'Prefix the customer number with this string for display purposes.',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'cust_main-custnum-display_special',
+    'section'     => 'UI',
+    'description' => 'Use this customer number prefix format',
+    'type'        => 'select',
+    'select_hash' => [ '' => '',
+                       'CoStAg' => 'CoStAg (country, state, agent name or display_prefix)',
+                       'CoStCl' => 'CoStCl (country, state, class name)' ],
+  },
+
+  {
+    'key'         => 'cust_main-custnum-display_length',
+    'section'     => 'UI',
+    'description' => 'Zero fill the customer number to this many digits for display purposes.',
+    'type'        => 'text',
+  },
+
+  {
     'key'         => 'cust_main-default_areacode',
     'section'     => 'UI',
     'description' => 'Default area code for customers.',
@@ -3804,6 +4376,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'unsuspend_email_admin',
+    'section'     => '',
+    'description' => 'Destination admin email address to enable unsuspension notices',
+    'type'        => 'text',
+  },
+  
+  {
     'key'         => 'email_report-subject',
     'section'     => '',
     'description' => 'Subject for reports emailed by freeside-fetch.  Defaults to "Freeside report".',
@@ -3853,6 +4432,22 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice-stripe1_bgcolor',
+    'section'     => 'self-service',
+    'description' => 'HTML color for self-service interface lists (primary stripe), for example, #FFFFFF',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'selfservice-stripe2_bgcolor',
+    'section'     => 'self-service',
+    'description' => 'HTML color for self-service interface lists (alternate stripe), for example, #DDDDDD',
+    'type'        => 'text',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'selfservice-text_color',
     'section'     => 'self-service',
     'description' => 'HTML text color for the self-service interface, for example, #000000',
@@ -3901,6 +4496,14 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice-no_logo',
+    'section'     => 'self-service',
+    'description' => 'Disable the logo in self-service',
+    'type'        => 'checkbox',
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'selfservice-title_color',
     'section'     => 'self-service',
     'description' => 'HTML color for the self-service title, for example, #000000',
@@ -3940,6 +4543,31 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'selfservice-menu_disable',
+    'section'     => 'self-service',
+    'description' => 'Disable the selected menu entries in the self-service menu',
+    'type'        => 'selectmultiple',
+    'select_enum' => [ #false laziness w/myaccount_menu.html
+                       'Overview',
+                       'Purchase',
+                       'Purchase additional package',
+                       'Recharge my account with a credit card',
+                       'Recharge my account with a check',
+                       'Recharge my account with a prepaid card',
+                       'View my usage',
+                       'Create a ticket',
+                       'Setup my services',
+                       'Change my information',
+                       'Change billing address',
+                       'Change service address',
+                       'Change payment information',
+                       'Change password(s)',
+                       'Logout',
+                     ],
+    'per_agent'   => 1,
+  },
+
+  {
     'key'         => 'selfservice-menu_skipblanks',
     'section'     => 'self-service',
     'description' => 'Skip blank (spacer) entries in the self-service menu',
@@ -4011,20 +4639,24 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'selfservice-bulk_format',
-    'section'     => 'deprecated',
-    'description' => 'Parameter arrangement for selfservice bulk features',
-    'type'        => 'select',
-    'select_enum' => [ '', 'izoom-soap', 'izoom-ftp' ],
-    'per_agent'   => 1,
+    'key'         => 'selfservice-login_banner_image',
+    'section'     => 'self-service',
+    'description' => 'Banner image shown on the login page, in PNG format.',
+    'type'        => 'image',
   },
 
   {
-    'key'         => 'selfservice-bulk_ftp_dir',
-    'section'     => 'deprecated',
-    'description' => 'Enable bulk ftp provisioning in this folder',
+    'key'         => 'selfservice-login_banner_url',
+    'section'     => 'self-service',
+    'description' => 'Link for the login banner.',
     'type'        => 'text',
-    'per_agent'   => 1,
+  },
+
+  {
+    'key'         => 'ng_selfservice-menu',
+    'section'     => 'self-service',
+    'description' => 'Custom menu for the next-generation self-service interface.  Each line is in the format "link Label", for example "main.php Home".  Sub-menu items are listed on subsequent lines.  Blank lines terminate the submenu.', #more docs/examples would be helpful
+    'type'        => 'textarea',
   },
 
   {
@@ -4082,7 +4714,14 @@ and customer address. Include units.',
     'description' => 'Maximum length of the phone service "Name" field (svc_phone.phone_name).  Sometimes useful to limit this (to 15?) when exporting as Caller ID data.',
     'type'        => 'text',
   },
-  
+
+  {
+    'key'         => 'svc_phone-random_pin',
+    'section'     => 'telephony',
+    'description' => 'Number of random digits to generate in the "PIN" field, if empty.',
+    'type'        => 'text',
+  },
+
   {
     'key'         => 'svc_phone-lnp',
     'section'     => 'telephony',
@@ -4163,45 +4802,38 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'cust_pkg-show_autosuspend',
-    'section'     => 'UI',
-    'description' => 'Show package auto-suspend dates.  Use with caution for now; can slow down customer view for large insallations.',
-    'type'        => 'checkbox',
-  },
-
-  {
-    'key'         => 'cdr-asterisk_forward_rewrite',
+    'key'         => 'cdr-taqua-callerid_rewrite',
     'section'     => 'telephony',
-    'description' => 'Enable special processing for CDRs representing forwarded calls: For CDRs that have a dcontext that starts with "Local/" but does not match dst, set charged_party to dst, parse a new dst from dstchannel, and set amaflags to "2" ("BILL"/"BILLING").',
+    'description' => 'For the Taqua CDR format, pull Caller ID blocking information from secondary CDRs.',
     'type'        => 'checkbox',
   },
 
   {
-    'key'         => 'sg-multicustomer_hack',
-    'section'     => '',
-    'description' => "Don't use this.",
+    'key'         => 'cdr-asterisk_australia_rewrite',
+    'section'     => 'telephony',
+    'description' => 'For Asterisk CDRs, assign CDR type numbers based on Australian conventions.',
     'type'        => 'checkbox',
   },
 
   {
-    'key'         => 'sg-ping_username',
-    'section'     => '',
-    'description' => "Don't use this.",
+    'key'         => 'cdr-gsm_tap3-sender',
+    'section'     => 'telephony',
+    'description' => 'GSM TAP3 Sender network (5 letter code)',
     'type'        => 'text',
   },
 
   {
-    'key'         => 'sg-ping_password',
-    'section'     => '',
-    'description' => "Don't use this.",
-    'type'        => 'text',
+    'key'         => 'cust_pkg-show_autosuspend',
+    'section'     => 'UI',
+    'description' => 'Show package auto-suspend dates.  Use with caution for now; can slow down customer view for large insallations.',
+    'type'        => 'checkbox',
   },
 
   {
-    'key'         => 'sg-login_username',
-    'section'     => '',
-    'description' => "Don't use this.",
-    'type'        => 'text',
+    'key'         => 'cdr-asterisk_forward_rewrite',
+    'section'     => 'telephony',
+    'description' => 'Enable special processing for CDRs representing forwarded calls: For CDRs that have a dcontext that starts with "Local/" but does not match dst, set charged_party to dst, parse a new dst from dstchannel, and set amaflags to "2" ("BILL"/"BILLING").',
+    'type'        => 'checkbox',
   },
 
   {
@@ -4250,10 +4882,35 @@ and customer address. Include units.',
   {
     'key'         => 'svc_broadband-manage_link',
     'section'     => 'UI',
-    'description' => 'URL for svc_broadband "Manage Device" link.  The following substitutions are available: $ip_addr.',
+    'description' => 'URL for svc_broadband "Manage Device" link.  The following substitutions are available: $ip_addr and $mac_addr.',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'svc_broadband-manage_link_text',
+    'section'     => 'UI',
+    'description' => 'Label for "Manage Device" link',
     'type'        => 'text',
   },
 
+  {
+    'key'         => 'svc_broadband-manage_link_loc',
+    'section'     => 'UI',
+    'description' => 'Location for "Manage Device" link',
+    'type'        => 'select',
+    'select_hash' => [
+      'bottom' => 'Near Unprovision link',
+      'right'  => 'With export-related links',
+    ],
+  },
+
+  {
+    'key'         => 'svc_broadband-manage_link-new_window',
+    'section'     => 'UI',
+    'description' => 'Open the "Manage Device" link in a new window',
+    'type'        => 'checkbox',
+  },
+
   #more fine-grained, service def-level control could be useful eventually?
   {
     'key'         => 'svc_broadband-allow_null_ip_addr',
@@ -4263,6 +4920,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'svc_hardware-check_mac_addr',
+    'section'     => '', #?
+    'description' => 'Require the "hardware address" field in hardware services to be a valid MAC address.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'tax-report_groups',
     'section'     => '',
     'description' => 'List of grouping possibilities for tax names on reports, one per line, "label op value" (op can be = or !=).',
@@ -4277,6 +4941,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'tax-cust_exempt-groups-require_individual_nums',
+    'section'     => '',
+    'description' => 'When using tax-cust_exempt-groups, require an individual tax exemption number for each exemption from different taxes.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'cust_main-default_view',
     'section'     => 'UI',
     'description' => 'Default customer view, for users who have not selected a default view in their preferences.',
@@ -4310,7 +4981,7 @@ and customer address. Include units.',
   {
     'key'         => 'pkg-balances',
     'section'     => 'billing',
-    'description' => 'Enable experimental package balances.  Not recommended for general use.',
+    'description' => 'Enable per-package balances.',
     'type'        => 'checkbox',
   },
 
@@ -4324,14 +4995,14 @@ and customer address. Include units.',
   {
     'key'         => 'cust_main-edit_signupdate',
     'section'     => 'UI',
-    'descritpion' => 'Enable manual editing of the signup date.',
+    'description' => 'Enable manual editing of the signup date.',
     'type'        => 'checkbox',
   },
 
   {
     'key'         => 'svc_acct-disable_access_number',
     'section'     => 'UI',
-    'descritpion' => 'Disable access number selection.',
+    'description' => 'Disable access number selection.',
     'type'        => 'checkbox',
   },
 
@@ -4420,16 +5091,16 @@ and customer address. Include units.',
   },
 
   {
-    'key'         => 'maestro-status_test',
+    'key'         => 'cust_main-custom_link',
     'section'     => 'UI',
-    'description' => 'Display a link to the maestro status test page on the customer view page',
-    'type'        => 'checkbox',
+    'description' => 'URL to use as source for the "Custom" tab in the View Customer page.  The customer number will be appended, or you can insert "$custnum" to have it inserted elsewhere.  "$agentnum" will be replaced with the agent number, and "$usernum" will be replaced with the employee number.',
+    'type'        => 'textarea',
   },
 
   {
-    'key'         => 'cust_main-custom_link',
+    'key'         => 'cust_main-custom_content',
     'section'     => 'UI',
-    'description' => 'URL to use as source for the "Custom" tab in the View Customer page.  The customer number will be appended, or you can insert "$custnum" to have it inserted elsewhere.  "$agentnum" will be replaced with the agent number.',
+    'description' => 'As an alternative to cust_main-custom_link (leave it blank), the contant to display on this customer page, one item per line.  Available iems are: small_custview, birthdate, spouse_birthdate, svc_acct, svc_phone and svc_external.',
     'type'        => 'textarea',
   },
 
@@ -4557,6 +5228,13 @@ and customer address. Include units.',
   },
 
   {
+    'key'         => 'invoice_payment_details',
+    'section'     => 'invoicing',
+    'description' => 'When displaying payments on an invoice, show the payment method used, including the check or credit card number.  Credit card numbers will be masked.',
+    'type'        => 'checkbox',
+  },
+
+  {
     'key'         => 'cust_main-status_module',
     'section'     => 'UI',
     'description' => 'Which module to use for customer status display.  The "Classic" module (the default) considers accounts with cancelled recurring packages but un-cancelled one-time charges Inactive.  The "Recurring" module considers those customers Cancelled.  Similarly for customers with suspended recurring packages but one-time charges.', #other differences?
@@ -4571,6 +5249,13 @@ and customer address. Include units.',
     'type'        => 'checkbox',
   },
 
+  { 
+    'key'         => 'username-exclamation',
+    'section'     => 'username',
+    'description' => 'Allow the exclamation character (!) in usernames.',
+    'type'        => 'checkbox',
+  },
+
   {
     'key'         => 'ie-compatibility_mode',
     'section'     => 'UI',
@@ -4595,8 +5280,8 @@ and customer address. Include units.',
   
   {
     'key'         => 'svc_broadband-require-nw-coordinates',
-    'section'     => 'UI',
-    'description' => 'On svc_broadband add/edit, require latitude and longitude in the North Western quadrant, e.g. for North American co-ordinates, etc.',
+    'section'     => 'deprecated',
+    'description' => 'Deprecated; see geocode-require_nw_coordinates instead',
     'type'        => 'checkbox',
   },
   
@@ -4608,16 +5293,16 @@ and customer address. Include units.',
   },
   
   {
-    'key'         => 'cust_main-require-bank-branch',
+    'key'         => 'cust-edit-alt-field-order',
     'section'     => 'UI',
-    'description' => 'An alternate DCHK/CHEK format; require entry of bank branch number.',
+    'description' => 'An alternate ordering of fields for the New Customer and Edit Customer screens.',
     'type'        => 'checkbox',
   },
-  
+
   {
-    'key'         => 'cust-edit-alt-field-order',
+    'key'         => 'cust_bill-enable_promised_date',
     'section'     => 'UI',
-    'description' => 'An alternate ordering of fields for the New Customer and Edit Customer screens.',
+    'description' => 'Enable display/editing of the "promised payment date" field on invoices.',
     'type'        => 'checkbox',
   },
   
@@ -4634,17 +5319,153 @@ and customer address. Include units.',
     },
     'option_sub'  => sub { FS::Locales->description(shift) },
   },
+
+  {
+    'key'         => 'cust_main-require_locale',
+    'section'     => 'UI',
+    'description' => 'Require an explicit locale to be chosen for new customers.',
+    'type'        => 'checkbox',
+  },
   
   {
     'key'         => 'translate-auto-insert',
     'section'     => '',
-    'description' => 'Auto-insert untranslated strings for selected non-en_US locales with their default/en_US values. DO NOT TURN THIS ON.',
+    'description' => 'Auto-insert untranslated strings for selected non-en_US locales with their default/en_US values.  Do not turn this on unless translating the interface into a new language.',
+    'type'        => 'select',
+    'multiple'    => 1,
+    'select_enum' => [ grep { $_ ne 'en_US' } FS::Locales::locales ],
+  },
+
+  {
+    'key'         => 'svc_acct-tower_sector',
+    'section'     => '',
+    'description' => 'Track tower and sector for svc_acct (account) services.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'cdr-prerate',
+    'section'     => 'telephony',
+    'description' => 'Experimental feature to rate CDRs immediately, rather than waiting until invoice generation time.  Can reduce invoice generation time when processing lots of CDRs.  Currently works with "VoIP/telco CDR rating (standard)" price plans using "Phone numbers (svc_phone.phonenum)" CDR service matching, without any included minutes.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'cdr-prerate-cdrtypenums',
+    'section'     => 'telephony',
+    'description' => 'When using cdr-prerate to rate CDRs immediately, limit processing to these CDR types.',
     'type'        => 'select-sub',
     'multiple'    => 1,
-    'options_sub' => sub { map { $_ => '' } 
-                            grep { $_ ne 'en_US' } FS::Locales::locales;
-                                    },
-    'option_sub'  => sub { ''; },
+    'options_sub' => sub { require FS::Record;
+                           require FS::cdr_type;
+                           map { $_->cdrtypenum => $_->cdrtypename }
+                               FS::Record::qsearch( 'cdr_type', 
+                                                   {} #{ 'disabled' => '' }
+                                                 );
+                        },
+    'option_sub'  => sub { require FS::Record;
+                           require FS::cdr_type;
+                           my $cdr_type = FS::Record::qsearchs(
+                            'cdr_type', { 'cdrtypenum'=>shift } );
+                           $cdr_type ? $cdr_type->cdrtypename : '';
+                        },
+  },
+
+  {
+    'key'         => 'cdr-minutes_priority',
+    'section'     => 'telephony',
+    'description' => 'Priority rule for assigning included minutes to CDRs.',
+    'type'        => 'select',
+    'select_hash' => [
+      ''          => 'No specific order',
+      'time'      => 'Chronological',
+      'rate_high' => 'Highest rate first',
+      'rate_low'  => 'Lowest rate first',
+    ],
+  },
+  
+  {
+    'key'         => 'brand-agent',
+    'section'     => 'UI',
+    'description' => 'Brand the backoffice interface (currently Help->About) using the company_name, company_url and logo.png configuration settings of the selected agent.  Typically used when selling or bundling hosted access to the backoffice interface.  NOTE: The AGPL software license has specific requirements for source code availability in this situation.',
+    'type'        => 'select-agent',
+  },
+
+  {
+    'key'         => 'cust_class-tax_exempt',
+    'section'     => 'billing',
+    'description' => 'Control the tax exemption flag per customer class rather than per indivual customer.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'selfservice-billing_history-line_items',
+    'section'     => 'self-service',
+    'description' => 'Return line item billing detail for the self-service billing_history API call.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'selfservice-default_cdr_format',
+    'section'     => 'self-service',
+    'description' => 'Format for showing outbound CDRs in self-service.  The per-package option overrides this.',
+    'type'        => 'select',
+    'select_hash' => \@cdr_formats,
+  },
+
+  {
+    'key'         => 'selfservice-default_inbound_cdr_format',
+    'section'     => 'self-service',
+    'description' => 'Format for showing inbound CDRs in self-service.  The per-package option overrides this.  Leave blank to avoid showing these CDRs.',
+    'type'        => 'select',
+    'select_hash' => \@cdr_formats,
+  },
+
+  {
+    'key'         => 'logout-timeout',
+    'section'     => 'UI',
+    'description' => 'If set, automatically log users out of the backoffice after this many minutes.',
+    'type'       => 'text',
+  },
+  
+  {
+    'key'         => 'spreadsheet_format',
+    'section'     => 'UI',
+    'description' => 'Default format for spreadsheet download.',
+    'type'        => 'select',
+    'select_hash' => [
+      'XLS' => 'XLS (Excel 97/2000/XP)',
+      'XLSX' => 'XLSX (Excel 2007+)',
+    ],
+  },
+
+  {
+    'key'         => 'agent-email_day',
+    'section'     => '',
+    'description' => 'On this day of each month, agents with master customer records containing email addresses will be emailed a list of their customers and balances.',
+    'type'        => 'text',
+  },
+
+  {
+    'key'         => 'report-cust_pay-select_time',
+    'section'     => 'UI',
+    'description' => 'Enable time selection on payment and refund reports.',
+    'type'        => 'checkbox',
+  },
+
+  {
+    'key'         => 'authentication_module',
+    'section'     => 'UI',
+    'description' => '"Internal" is the default , which authenticates against the internal database.  "Legacy" is similar, but matches passwords against a legacy htpasswd file.',
+    'type'        => 'select',
+    'select_enum' => [qw( Internal Legacy )],
+  },
+
+  {
+    'key'         => 'external_auth-access_group-template_user',
+    'section'     => 'UI',
+    'description' => 'When using an external authentication module, specifies the default access groups for autocreated users, via a template user.',
+    'type'        => 'text',
   },
 
   { key => "apacheroot", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },