package FS::Conf;
-use vars qw($base_dir @config_items @base_items @card_types $DEBUG);
+use strict;
+use vars qw( $base_dir @config_items @base_items @card_types $DEBUG
+ $conf_cache $conf_cache_enabled
+ );
use Carp;
use IO::File;
use File::Basename;
use Locale::Currency;
use FS::ConfItem;
use FS::ConfDefaults;
-use FS::Conf_compat17;
use FS::Locales;
use FS::payby;
use FS::conf;
use FS::Record qw(qsearch qsearchs);
-use FS::UID qw(dbh datasrc use_confcompat);
+use FS::UID qw(dbh datasrc);
use FS::Misc::Invoicing qw( spool_formats );
$base_dir = '%%%FREESIDE_CONF%%%';
$DEBUG = 0;
+$conf_cache_enabled = 0;
+
=head1 NAME
FS::Conf - Freeside configuration values
=cut
-sub _usecompat {
- my ($self, $method) = (shift, shift);
- carp "NO CONFIGURATION RECORDS FOUND -- USING COMPATIBILITY MODE"
- if use_confcompat;
- my $compat = new FS::Conf_compat17 ("$base_dir/conf." . datasrc);
- $compat->$method(@_);
-}
-
sub _config {
my($self,$name,$agentnum,$agentonly)=@_;
my $hashref = { 'name' => $name };
local $FS::Record::conf = undef; # XXX evil hack prevents recursion
+ $conf_cache = undef unless $conf_cache_enabled; # use cache only when it is
+ # safe to do so
my $cv;
my @a = (
($agentnum || ()),
foreach my $a (@a) {
$hashref->{agentnum} = $a;
foreach my $l (@l) {
- $hashref->{locale} = $l;
- $cv = FS::Record::qsearchs('conf', $hashref);
- return $cv if $cv;
+ my $key = join(':',$name, $a, $l);
+ if (! exists $conf_cache->{$key}){
+ $hashref->{locale} = $l;
+ # $conf_cache is reset in FS::UID during myconnect, so the cache is
+ # reset per connection
+ $conf_cache->{$key} = FS::Record::qsearchs('conf', $hashref);
+ }
+ return $conf_cache->{$key} if $conf_cache->{$key};
}
}
return undef;
sub config {
my $self = shift;
- return $self->_usecompat('config', @_) if use_confcompat;
carp "FS::Conf->config(". join(', ', @_). ") called"
if $DEBUG > 1;
sub config_binary {
my $self = shift;
- return $self->_usecompat('config_binary', @_) if use_confcompat;
my $cv = $self->_config(@_) or return;
length($cv->value) ? decode_base64($cv->value) : '';
sub exists {
my $self = shift;
- return $self->_usecompat('exists', @_) if use_confcompat;
#my($name, $agentnum)=@_;
sub config_bool {
my $self = shift;
- return $self->_usecompat('exists', @_) if use_confcompat;
my($name,$agentnum,$agentonly) = @_;
# these to fall back to standard values
sub config_orbase {
my $self = shift;
- return $self->_usecompat('config_orbase', @_) if use_confcompat;
my( $name, $suffix ) = @_;
if ( $self->exists("${name}_$suffix") ) {
sub key_orbase {
my $self = shift;
- #no compat for this...return $self->_usecompat('config_orbase', @_) if use_confcompat;
my( $name, $suffix ) = @_;
if ( $self->exists("${name}_$suffix") ) {
sub touch {
my $self = shift;
- return $self->_usecompat('touch', @_) if use_confcompat;
my($name, $agentnum) = @_;
#unless ( $self->exists($name, $agentnum) ) {
sub set {
my $self = shift;
- return $self->_usecompat('set', @_) if use_confcompat;
my($name, $value, $agentnum) = @_;
$value =~ /^(.*)$/s;
$error = $new->insert;
}
+ if (! $error) {
+ # clean the object cache
+ my $key = join(':',$name, $agentnum, $self->{locale});
+ $conf_cache->{ $key } = $new;
+ }
+
die "error setting configuration value: $error \n"
if $error;
sub set_binary {
my $self = shift;
- return if use_confcompat;
my($name, $value, $agentnum)=@_;
$self->set($name, encode_base64($value), $agentnum);
sub delete {
my $self = shift;
- return $self->_usecompat('delete', @_) if use_confcompat;
my($name, $agentnum) = @_;
if ( my $cv = FS::Record::qsearchs('conf', {name => $name, agentnum => $agentnum, locale => $self->{locale}}) ) {
sub delete_bool {
my $self = shift;
- return $self->_usecompat('delete', @_) if use_confcompat;
my($name, $agentnum) = @_;
sub import_config_item {
my ($self,$item,$dir) = @_;
my $key = $item->key;
- if ( -e "$dir/$key" && ! use_confcompat ) {
+ if ( -e "$dir/$key" ) {
warn "Inserting $key\n" if $DEBUG;
local $/;
my $value = readline(new IO::File "$dir/$key");
}else{
$self->set($key, $value);
}
- }else {
- warn "Not inserting $key\n" if $DEBUG;
- }
-}
-
-=item verify_config_item CONFITEM DIR
-
- Compares the item specified by the CONFITEM (see L<FS::ConfItem>) in
-the database to the legacy file value in DIR.
-
-=cut
-
-sub verify_config_item {
- return '' if use_confcompat;
- my ($self,$item,$dir) = @_;
- my $key = $item->key;
- my $type = $item->type;
-
- my $compat = new FS::Conf_compat17 $dir;
- my $error = '';
-
- $error .= "$key fails existential comparison; "
- if $self->exists($key) xor $compat->exists($key);
-
- if ( $type !~ /^(binary|image)$/ ) {
-
- {
- no warnings;
- $error .= "$key fails scalar comparison; "
- unless scalar($self->config($key)) eq scalar($compat->config($key));
- }
-
- my (@new) = $self->config($key);
- my (@old) = $compat->config($key);
- unless ( scalar(@new) == scalar(@old)) {
- $error .= "$key fails list comparison; ";
- }else{
- my $r=1;
- foreach (@old) { $r=0 if ($_ cmp shift(@new)); }
- $error .= "$key fails list comparison; "
- unless $r;
- }
-
} else {
-
- no warnings 'uninitialized';
- $error .= "$key fails binary comparison; "
- unless scalar($self->config_binary($key)) eq scalar($compat->config_binary($key));
-
+ warn "Not inserting $key\n" if $DEBUG;
}
-
-#remove deprecated config on our own terms, not freeside-upgrade's
-# if ($error =~ /existential comparison/ && $item->section eq 'deprecated') {
-# my $proto;
-# for ( @config_items ) { $proto = $_; last if $proto->key eq $key; }
-# unless ($proto->key eq $key) {
-# warn "removed config item $error\n" if $DEBUG;
-# $error = '';
-# }
-# }
-
- $error;
}
#item _orbase_items OPTIONS
sub config_items {
my $self = shift;
- return $self->_usecompat('config_items', @_) if use_confcompat;
( @config_items, $self->_orbase_items(@_) );
}
sub init_config {
my $dir = shift;
- {
- local $FS::UID::use_confcompat = 0;
- my $conf = new FS::Conf;
- foreach my $item ( $conf->config_items(dir => $dir) ) {
- $conf->import_config_item($item, $dir);
- my $error = $conf->verify_config_item($item, $dir);
- return $error if $error;
- }
-
- my $compat = new FS::Conf_compat17 $dir;
- foreach my $item ( $compat->config_items ) {
- my $error = $conf->verify_config_item($item, $dir);
- return $error if $error;
- }
+ my $conf = new FS::Conf;
+ foreach my $item ( $conf->config_items(dir => $dir) ) {
+ $conf->import_config_item($item, $dir);
}
- $FS::UID::use_confcompat = 0;
''; #success
}
invoice_latexsmallfooter
invoice_latexnotes
invoice_latexcoupon
+invoice_latexwatermark
invoice_html
invoice_htmlreturnaddress
invoice_htmlfooter
invoice_htmlnotes
+invoice_htmlwatermark
logo.png
logo.eps
);
},
);
+my %invoice_mode_options = (
+ 'type' => 'select-sub',
+ 'options_sub' => sub {
+ my @modes = qsearch({
+ 'table' => 'invoice_mode',
+ 'extra_sql' => ' WHERE '.
+ $FS::CurrentUser::CurrentUser->agentnums_sql(null => 1),
+ });
+ map { $_->modenum, $_->modename } @modes;
+ },
+ 'option_sub' => sub {
+ my $mode = FS::invoice_mode->by_key(shift);
+ $mode ? $mode->modename : '',
+ },
+ 'per_agent' => 1,
+);
+
my @cdr_formats = (
'' => '',
'default' => 'Default',
}
}
+my $validate_email = sub { $_[0] =~
+ /^[^@]+\@[[:alnum:]-]+(\.[[:alnum:]-]+)+$/
+ ? '' : 'Invalid email address';
+ };
+
#Billing (81 items)
#Invoicing (50 items)
#UI (69 items)
@config_items = map { new FS::ConfItem $_ } (
- {
- 'key' => 'address',
- 'section' => 'deprecated',
- 'description' => 'This configuration option is no longer used. See <a href="#invoice_template">invoice_template</a> instead.',
- 'type' => 'text',
- },
-
{
'key' => 'event_log_level',
'section' => 'notification',
'per_locale' => 1,
},
- {
- '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 void or apply a credit against the invoice instead.',
- 'type' => 'checkbox',
- },
-
{
'key' => 'deletecredits',
#not actually deprecated yet
'type' => 'checkbox',
},
- {
- 'key' => 'unapplypayments',
- 'section' => 'deprecated',
- 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable "unapplication" of unclosed payments.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'unapplycredits',
- 'section' => 'deprecated',
- 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable "unapplication" of unclosed credits.',
- 'type' => 'checkbox',
- },
-
{
'key' => 'dirhash',
'section' => 'shell',
'description' => 'Return address on email invoices (address only, see invoice_from_name)',
'type' => 'text',
'per_agent' => 1,
- 'validate' => sub { $_[0] =~
- /^[^@]+\@[[:alnum:]-]+(\.[[:alnum:]-]+)+$/
- ? '' : 'Invalid email address';
- }
+ 'validate' => $validate_email,
},
{
'per_locale' => 1,
},
+ {
+ 'key' => 'invoice_htmlwatermark',
+ 'section' => 'invoicing',
+ 'description' => 'Watermark for HTML invoices. Appears in a semitransparent positioned DIV overlaid on the main invoice container.',
+ 'type' => 'textarea',
+ 'per_agent' => 1,
+ 'per_locale' => 1,
+ },
+
{
'key' => 'invoice_latex',
'section' => 'invoicing',
'per_locale' => 1,
},
+ {
+ 'key' => 'invoice_latexwatermark',
+ 'section' => 'invoicing',
+ 'description' => 'Watermark for LaTeX invoices. See "texdoc background" for information on what this can contain. The content itself should be enclosed in braces, optionally followed by a comma and any formatting options.',
+ 'type' => 'textarea',
+ 'per_agent' => 1,
+ 'per_locale' => 1,
+ },
+
{
'key' => 'invoice_email_pdf',
'section' => 'invoicing',
'type' => 'checkbox'
},
+ {
+ 'key' => 'invoice_email_pdf_msgnum',
+ 'section' => 'invoicing',
+ 'description' => 'Message template to send as the text and HTML part of PDF invoices. If not selected, a text and HTML version of the invoice will be sent.',
+ %msg_template_options,
+ },
+
{
'key' => 'invoice_email_pdf_note',
'section' => 'invoicing',
'type' => 'select',
'per_agent' => 1,
'select_enum' => [
- '', 'Payable upon receipt', 'Net 0', 'Net 3', 'Net 5', 'Net 9', 'Net 10', 'Net 14',
+ '', 'Payable upon receipt', 'Net 0', 'Net 3', 'Net 5', 'Net 7', 'Net 9', 'Net 10', 'Net 14',
'Net 15', 'Net 18', 'Net 20', 'Net 21', 'Net 25', 'Net 30', 'Net 45',
'Net 60', 'Net 90'
], },
'type' => 'checkbox',
},
- {
- 'key' => 'invoice_send_receipts',
- 'section' => 'deprecated',
- 'description' => '<b>DEPRECATED</b>, this used to send an invoice copy on payments and credits. See the payment_receipt_email and XXXX instead.',
- 'type' => 'checkbox',
- },
-
{
'key' => 'payment_receipt',
'section' => 'notification',
'agent_bool' => 1,
},
+ {
+ 'key' => 'payment_receipt_statement_mode',
+ 'section' => 'notification',
+ 'description' => 'Automatic payments will cause a post-payment statement to be sent to the customer. Select the invoice mode to use for this statement. If unspecified, it will use the "_statement" versions of invoice configuration settings, and have the notice name "Statement".',
+ %invoice_mode_options,
+ },
+
{
'key' => 'payment_receipt_msgnum',
'section' => 'notification',
- 'description' => 'Template to use for payment receipts.',
+ 'description' => 'Template to use for manual payment receipts.',
%msg_template_options,
},
# 'description' => 'Directory which contains domain registry information. Each registry is a directory.',
# },
- {
- 'key' => 'report_template',
- 'section' => 'deprecated',
- 'description' => 'Deprecated template file for reports.',
- 'type' => 'textarea',
- },
-
{
'key' => 'maxsearchrecordsperpage',
'section' => 'UI',
'type' => 'checkbox',
},
- {
-
{
'key' => 'show_ship_company',
'section' => 'UI',
'svc_acct' => 'Account (svc_acct)',
'svc_phone' => 'Phone number (svc_phone)',
'svc_pbx' => 'PBX (svc_pbx)',
+ 'none' => 'None - package only',
],
},
{
'key' => 'enable_taxclasses',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Enable per-package tax classes',
'type' => 'checkbox',
},
{
'key' => 'require_taxclasses',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Require a taxclass to be entered for every package',
'type' => 'checkbox',
},
{
- 'key' => 'enable_taxproducts',
- 'section' => 'billing',
+ 'key' => 'tax_data_vendor',
+ 'section' => 'taxation',
'description' => 'Tax data vendor you are using.',
'type' => 'select',
- 'select_enum' => [ 'cch', 'billsoft', 'avalara' ],
+ 'select_enum' => [ '', 'cch', 'billsoft', 'avalara', 'suretax' ],
},
{
'key' => 'taxdatadirectdownload',
- 'section' => 'billing', #well
- 'description' => 'Enable downloading tax data directly from the vendor site. at least three lines: URL, username, and password.j',
+ 'section' => 'taxation',
+ 'description' => 'Enable downloading tax data directly from CCH. at least three lines: URL, username, and password.j',
'type' => 'textarea',
},
{
'key' => 'ignore_incalculable_taxes',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Prefer to invoice without tax over not billing at all',
'type' => 'checkbox',
},
{
'key' => 'billsoft-company_code',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Billsoft tax service company code (3 letters)',
'type' => 'text',
},
{
'key' => 'avalara-taxconfig',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Avalara tax service configuration. Four lines: company code, account number, license key, test mode (1 to enable).',
'type' => 'textarea',
},
+ {
+ 'key' => 'suretax-hostname',
+ 'section' => 'taxation',
+ 'description' => 'SureTax server name; defaults to the test server.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'suretax-client_number',
+ 'section' => 'taxation',
+ 'description' => 'SureTax tax service client ID.',
+ 'type' => 'text',
+ },
+ {
+ 'key' => 'suretax-validation_key',
+ 'section' => 'taxation',
+ 'description' => 'SureTax validation key (UUID).',
+ 'type' => 'text',
+ },
+ {
+ 'key' => 'suretax-business_unit',
+ 'section' => 'taxation',
+ 'description' => 'SureTax client business unit name; optional.',
+ 'type' => 'text',
+ 'per_agent' => 1,
+ },
+ {
+ 'key' => 'suretax-regulatory_code',
+ 'section' => 'taxation',
+ 'description' => 'SureTax client regulatory status.',
+ 'type' => 'select',
+ 'select_enum' => [ '', 'ILEC', 'IXC', 'CLEC', 'VOIP', 'ISP', 'Wireless' ],
+ 'per_agent' => 1,
+ },
+
+
{
'key' => 'welcome_msgnum',
'section' => 'notification',
'section' => 'billing',
'description' => 'Available payment types.',
'type' => 'selectmultiple',
- 'select_enum' => [ qw(CARD DCRD CHEK DCHK CASH WEST MCRD MCHK PPAL) ],
+ 'select_enum' => [ qw(CARD DCRD CHEK DCHK BILL CASH WEST MCRD MCHK PPAL) ],
+ },
+
+ {
+ 'key' => 'banned_pay-pad',
+ 'section' => 'billing',
+ 'description' => 'Padding for encrypted storage of banned credit card hashes. If you already have new-style SHA512 entries in the banned_pay table, do not change as this will invalidate the old entries.',
+ 'type' => 'text',
},
{
'type' => 'checkbox',
},
- {
- 'key' => 'paymentforcedtobatch',
- 'section' => 'deprecated',
- 'description' => 'See batch-enable_payby and realtime-disable_payby. Used to (for CHEK): Cause per customer payment entry to be forced to a batch processor rather than performed realtime.',
- 'type' => 'checkbox',
- },
-
{
'key' => 'svc_acct-notes',
'section' => 'deprecated',
},
{
- 'key' => 'users-allow_comp',
- 'section' => 'deprecated',
- 'description' => '<b>DEPRECATED</b>, enable the <i>Complimentary customer</i> access right instead. Was: Usernames (Freeside users, created with <a href="../docs/man/bin/freeside-adduser.html">freeside-adduser</a>) which can create complimentary customers, one per line. If no usernames are entered, all users can create complimentary accounts.',
- 'type' => 'textarea',
+ 'key' => 'dump-email_to',
+ 'section' => '',
+ 'description' => "Optional email address to send success/failure message for database dumps.",
+ 'type' => 'text',
+ 'validate' => $validate_email,
},
{
'type' => 'checkbox',
},
+ {
+ 'key' => 'manual_process-single_invoice_amount',
+ 'section' => 'billing',
+ 'description' => 'When entering manual credit card and ACH payments, amount will not autofill if the customer has more than one open invoice',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'manual_process-pkgpart',
'section' => 'billing',
},
'option_sub' => sub { require FS::Record;
require FS::agent_type;
- my $agent = FS::Record::qsearchs(
+ my $agent_type = FS::Record::qsearchs(
'agent_type', { 'typenum'=>shift }
);
$agent_type ? $agent_type->atype : '';
}
},
},
+
{
'key' => 'ticket_system-force_default_queueid',
'section' => 'ticketing',
'description' => 'Disallow queue selection when creating new tickets from customer view.',
'type' => 'checkbox',
},
+
{
'key' => 'ticket_system-selfservice_queueid',
'section' => 'ticketing',
'type' => 'checkbox',
},
+ {
+ 'key' => 'ticket_system-appointment-queueid',
+ 'section' => 'ticketing',
+ 'description' => 'Custom field from the ticketing system to use as an appointment classification.',
+ #false laziness w/above
+ 'type' => 'select-sub',
+ 'options_sub' => sub {
+ my $conf = new FS::Conf;
+ if ( $conf->config('ticket_system') ) {
+ eval "use FS::TicketSystem;";
+ die $@ if $@;
+ FS::TicketSystem->queues();
+ } else {
+ ();
+ }
+ },
+ 'option_sub' => sub {
+ my $conf = new FS::Conf;
+ if ( $conf->config('ticket_system') ) {
+ eval "use FS::TicketSystem;";
+ die $@ if $@;
+ FS::TicketSystem->queue(shift);
+ } else {
+ '';
+ }
+ },
+ },
+
{
'key' => 'ticket_system-escalation',
'section' => 'ticketing',
'per_agent' => 1,
},
- {
- 'key' => 'city_not_required',
- 'section' => 'required',
- 'description' => 'Turn off requirement for a City to be entered for billing & shipping addresses',
- 'type' => 'checkbox',
- 'per_agent' => 1,
- },
-
- {
- 'key' => 'echeck-void',
- 'section' => 'deprecated',
- 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable local-only voiding of echeck payments in addition to refunds against the payment gateway',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'cc-void',
- 'section' => 'deprecated',
- 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable local-only voiding of credit card payments in addition to refunds against the payment gateway',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'unvoid',
- 'section' => 'deprecated',
- 'description' => '<B>DEPRECATED</B>, now controlled by ACLs. Used to enable unvoiding of voided payments',
- 'type' => 'checkbox',
- },
-
{
'key' => 'address1-search',
'section' => 'UI',
'per_agent' => 1,
},
- { 'key' => 'referral_credit',
- 'section' => 'deprecated',
- 'description' => "Used to enable one-time referral credits in the amount of one month <i>referred</i> customer's recurring fee (irregardless of frequency). Replace with a billing event on appropriate packages.",
- 'type' => 'checkbox',
- },
-
{ 'key' => 'selfservice_server-cache_module',
'section' => 'self-service',
'description' => 'Module used to store self-service session information. All modules handle any number of self-service servers. Cache::SharedMemoryCache is appropriate for a single database / single Freeside server. Cache::FileCache is useful for multiple databases on a single server, or when IPC::ShareLite is not available (i.e. FreeBSD).', # _Database stores session information in the database and is appropriate for multiple Freeside servers, but may be slower.',
{
'key' => 'tax-ship_address',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'By default, tax calculations are done based on the billing address. Enable this switch to calculate tax based on the shipping address instead.',
'type' => 'checkbox',
}
,
{
'key' => 'tax-pkg_address',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'By default, tax calculations are done based on the billing address. Enable this switch to calculate tax based on the package address instead (when present).',
'type' => 'checkbox',
},
{
'key' => 'batchconfig-RBC',
'section' => 'billing',
- 'description' => 'Configuration for Royal Bank of Canada PDS batching, four lines: 1. Client number, 2. Short name, 3. Long name, 4. Transaction code.',
+ 'description' => 'Configuration for Royal Bank of Canada PDS batching, five lines: 1. Client number, 2. Short name, 3. Long name, 4. Transaction code 5. (optional) set to TEST to turn on test mode.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'batchconfig-RBC-login',
+ 'section' => 'billing',
+ 'description' => 'FTPS login for uploading Royal Bank of Canada batches. Two lines: 1. username, 2. password. If not supplied, batches can still be created but not automatically uploaded.',
'type' => 'textarea',
},
'type' => 'text',
},
+ {
+ 'key' => 'batchconfig-nacha-origin_name',
+ 'section' => 'billing',
+ 'description' => 'Configuration for NACHA batching, Origin name (defaults to company name, but sometimes bank name is needed instead.)',
+ 'type' => 'text',
+ },
+
{
'key' => 'batch-manual_approval',
'section' => 'billing',
{
'key' => 'disable_previous_balance',
'section' => 'invoicing',
- 'description' => 'Disable inclusion of previous balance, payment, and credit lines on invoices.',
+ 'description' => 'Show new charges only; do not list previous invoices, payments, or credits on the invoice.',
'type' => 'checkbox',
'per_agent' => 1,
},
{
'key' => 'previous_balance-exclude_from_total',
'section' => 'invoicing',
- 'description' => 'Do not include previous balance in the \'Total\' line. Only meaningful when invoice_sections is false. Optionally provide text to override the Total New Charges description',
- 'type' => [ qw(checkbox text) ],
+ 'description' => 'Show separate totals for previous invoice balance and new charges. Only meaningful when invoice_sections is false.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'previous_balance-text',
+ 'section' => 'invoicing',
+ 'description' => 'Text for the label of the total previous balance, when it is shown separately. Defaults to "Previous Balance".',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'previous_balance-text-total_new_charges',
+ 'section' => 'invoicing',
+ 'description' => 'Text for the label of the total of new charges, when it is shown separately. If invoice_show_prior_due_date is enabled, the due date of current charges will be appended. Defaults to "Total New Charges".',
+ 'type' => 'text',
},
{
'section' => 'invoicing',
'description' => 'Instead of showing payments (and credits) applied to the invoice, show those received since the previous invoice date.',
'type' => 'checkbox',
+ 'uscensus' => 'U.S. Census Bureau',
},
{
'type' => 'checkbox',
},
+ {
+ 'key' => 'cust_main-no_city_in_address',
+ 'section' => 'UI',
+ 'description' => 'Turn off City for billing & shipping addresses',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'census_year',
'section' => 'UI',
{
'key' => 'tax_district_method',
- 'section' => 'UI',
+ 'section' => 'taxation',
'description' => 'The method to use to look up tax district codes.',
'type' => 'select',
#'select_hash' => [ FS::Misc::Geo::get_district_methods() ],
{
'key' => 'tax-cust_exempt-groups',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'List of grouping possibilities for tax names, for per-customer exemption purposes, one tax name per line. For example, "GST" would indicate the ability to exempt customers individually from taxes named "GST" (but not other taxes).',
'type' => 'textarea',
},
{
'key' => 'tax-cust_exempt-groups-num_req',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'When using tax-cust_exempt-groups, control whether individual tax exemption numbers are required for exemption from different taxes.',
'type' => 'select',
'select_hash' => [ '' => 'Not required',
{
'key' => 'enable_tax_adjustments',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Enable the ability to add manual tax adjustments.',
'type' => 'checkbox',
},
{
'key' => 'cust_class-tax_exempt',
- 'section' => 'billing',
+ 'section' => 'taxation',
'description' => 'Control the tax exemption flag per customer class rather than per indivual customer.',
'type' => 'checkbox',
},
'type' => 'checkbox',
},
+ {
+ 'key' => 'selfservice-enable_payment_without_balance',
+ 'section' => 'self-service',
+ 'description' => 'Allow selfservice customers to make payments even if balance is zero or below (resulting in an unapplied payment and negative balance.)',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'logout-timeout',
'section' => 'UI',
'type' => 'checkbox',
},
- { key => "apacheroot", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "apachemachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "apachemachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "bindprimary", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "bindsecondaries", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "bsdshellmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "cyrus", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "cp_app", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "erpcdmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "icradiusmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "icradius_mysqldest", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "icradius_mysqlsource", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "icradius_secrets", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "maildisablecatchall", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "mxmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "nsmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "arecords", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "cnamerecords", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "nismachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "qmailmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "radiusmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "sendmailconfigpath", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "sendmailmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "sendmailrestart", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "shellmachine", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "shellmachine-useradd", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "shellmachine-userdel", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "shellmachine-usermod", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "shellmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "radiusprepend", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "textradiusprepend", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "username_policy", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "vpopmailmachines", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "vpopmailrestart", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "safe-part_pkg", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "selfservice_server-quiet", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "signup_server-quiet", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "signup_server-email", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "vonage-username", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "vonage-password", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
- { key => "vonage-fromnumber", section => "deprecated", description => "<b>DEPRECATED</b>", type => "text" },
+ {
+ 'key' => 'default_appointment_length',
+ 'section' => 'UI',
+ 'description' => 'Default appointment length, in minutes (30 minute granularity).',
+ 'type' => 'text',
+ },
+
+ # for internal use only; test databases should declare this option and
+ # everyone else should pretend it doesn't exist
+ #{
+ # 'key' => 'no_random_ids',
+ # 'section' => '',
+ # 'description' => 'Replace random identifiers in UI code with a static string, for repeatable testing. Don\'t use in production.',
+ # 'type' => 'checkbox',
+ #},
);