X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FConf.pm;h=5c4774ab5dca38781126619ddf1766245f0400e0;hb=15a4e1674694b76ecc2af87de479aabe370ac03d;hp=bb04d9427fce917181bbc6a948bee2c1ddf7056a;hpb=2c5aa117162ef4dfce93da42ea3391dcdece4bb9;p=freeside.git diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index bb04d9427..5c4774ab5 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -1,6 +1,9 @@ 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; @@ -8,18 +11,19 @@ use MIME::Base64; 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 @@ -108,18 +112,12 @@ specific value(s) is returned. =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 || ()), @@ -133,9 +131,14 @@ sub _config { 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; @@ -143,7 +146,6 @@ sub _config { sub config { my $self = shift; - return $self->_usecompat('config', @_) if use_confcompat; carp "FS::Conf->config(". join(', ', @_). ") called" if $DEBUG > 1; @@ -167,7 +169,6 @@ Returns the exact scalar value for key. 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) : ''; @@ -182,7 +183,6 @@ is undefined. sub exists { my $self = shift; - return $self->_usecompat('exists', @_) if use_confcompat; #my($name, $agentnum)=@_; @@ -197,7 +197,6 @@ sub exists { sub config_bool { my $self = shift; - return $self->_usecompat('exists', @_) if use_confcompat; my($name,$agentnum,$agentonly) = @_; @@ -252,7 +251,6 @@ KEY_SUFFIX, if it exists, otherwise for KEY # 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") ) { @@ -272,7 +270,6 @@ config_orbase. 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") ) { @@ -315,7 +312,6 @@ Creates the specified configuration key if it does not exist. sub touch { my $self = shift; - return $self->_usecompat('touch', @_) if use_confcompat; my($name, $agentnum) = @_; #unless ( $self->exists($name, $agentnum) ) { @@ -336,7 +332,6 @@ Sets the specified configuration key to the given value. sub set { my $self = shift; - return $self->_usecompat('set', @_) if use_confcompat; my($name, $value, $agentnum) = @_; $value =~ /^(.*)$/s; @@ -361,6 +356,12 @@ sub set { $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; @@ -375,7 +376,6 @@ can be retrieved with config_binary. sub set_binary { my $self = shift; - return if use_confcompat; my($name, $value, $agentnum)=@_; $self->set($name, encode_base64($value), $agentnum); @@ -389,7 +389,6 @@ Deletes the specified configuration key. 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}}) ) { @@ -416,7 +415,6 @@ sub delete { sub delete_bool { my $self = shift; - return $self->_usecompat('delete', @_) if use_confcompat; my($name, $agentnum) = @_; @@ -447,7 +445,7 @@ in the directory DIR. 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"); @@ -456,68 +454,9 @@ sub import_config_item { }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) 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 @@ -588,7 +527,6 @@ FS::ConfItem objects. See L. sub config_items { my $self = shift; - return $self->_usecompat('config_items', @_) if use_confcompat; ( @config_items, $self->_orbase_items(@_) ); } @@ -624,23 +562,11 @@ to conf records in the database. 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 } @@ -679,10 +605,12 @@ invoice_latexfooter invoice_latexsmallfooter invoice_latexnotes invoice_latexcoupon +invoice_latexwatermark invoice_html invoice_htmlreturnaddress invoice_htmlfooter invoice_htmlnotes +invoice_htmlwatermark logo.png logo.eps ); @@ -733,6 +661,23 @@ my %batch_gateway_options = ( }, ); +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', @@ -760,6 +705,11 @@ sub reason_type_options { } } +my $validate_email = sub { $_[0] =~ + /^[^@]+\@[[:alnum:]-]+(\.[[:alnum:]-]+)+$/ + ? '' : 'Invalid email address'; + }; + #Billing (81 items) #Invoicing (50 items) #UI (69 items) @@ -769,13 +719,6 @@ sub reason_type_options { @config_items = map { new FS::ConfItem $_ } ( - { - 'key' => 'address', - 'section' => 'deprecated', - 'description' => 'This configuration option is no longer used. See invoice_template instead.', - 'type' => 'text', - }, - { 'key' => 'event_log_level', 'section' => 'notification', @@ -1095,23 +1038,6 @@ sub reason_type_options { '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 - #'section' => 'deprecated', - #'description' => 'DEPRECATED, now controlled by ACLs. Used to enable deletion of unclosed credits. Be very careful! Only delete credits that were data-entry errors, not adjustments. Optionally specify one or more comma-separated email addresses to be notified when a credit is deleted.', - 'section' => '', - 'description' => 'One or more comma-separated email addresses to be notified when a credit is deleted.', - 'type' => [qw( checkbox text )], - }, - { 'key' => 'deleterefunds', 'section' => 'billing', @@ -1119,20 +1045,6 @@ sub reason_type_options { 'type' => 'checkbox', }, - { - 'key' => 'unapplypayments', - 'section' => 'deprecated', - 'description' => 'DEPRECATED, now controlled by ACLs. Used to enable "unapplication" of unclosed payments.', - 'type' => 'checkbox', - }, - - { - 'key' => 'unapplycredits', - 'section' => 'deprecated', - 'description' => 'DEPRECATED, now controlled by ACLs. Used to enable "unapplication" of unclosed credits.', - 'type' => 'checkbox', - }, - { 'key' => 'dirhash', 'section' => 'shell', @@ -1251,10 +1163,7 @@ sub reason_type_options { '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, }, { @@ -1360,6 +1269,15 @@ sub reason_type_options { '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', @@ -1547,6 +1465,15 @@ and customer address. Include units.', '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', @@ -1561,6 +1488,13 @@ and customer address. Include units.', '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', @@ -1697,13 +1631,6 @@ and customer address. Include units.', 'type' => 'checkbox', }, - { - 'key' => 'invoice_send_receipts', - 'section' => 'deprecated', - 'description' => 'DEPRECATED, 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', @@ -1713,10 +1640,17 @@ and customer address. Include units.', '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, }, @@ -1894,13 +1828,6 @@ and customer address. Include units.', # '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', @@ -2146,8 +2073,6 @@ and customer address. Include units.', 'type' => 'checkbox', }, - { - { 'key' => 'show_ship_company', 'section' => 'UI', @@ -2340,6 +2265,7 @@ and customer address. Include units.', 'svc_acct' => 'Account (svc_acct)', 'svc_phone' => 'Phone number (svc_phone)', 'svc_pbx' => 'PBX (svc_pbx)', + 'none' => 'None - package only', ], }, @@ -2496,54 +2422,90 @@ and customer address. Include units.', { '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', @@ -2647,7 +2609,14 @@ and customer address. Include units.', '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', }, { @@ -2665,13 +2634,6 @@ and customer address. Include units.', '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', @@ -2738,13 +2700,6 @@ and customer address. Include units.', 'type' => 'text', }, - { - 'key' => 'users-allow_comp', - 'section' => 'deprecated', - 'description' => 'DEPRECATED, enable the Complimentary customer access right instead. Was: Usernames (Freeside users, created with freeside-adduser) which can create complimentary customers, one per line. If no usernames are entered, all users can create complimentary accounts.', - 'type' => 'textarea', - }, - { 'key' => 'credit_card-recurring_billing_flag', 'section' => 'billing', @@ -2799,6 +2754,13 @@ and customer address. Include units.', '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', @@ -3049,7 +3011,7 @@ and customer address. Include units.', }, '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 : ''; @@ -3346,35 +3308,6 @@ and customer address. Include units.', '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' => 'DEPRECATED, 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' => 'DEPRECATED, 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' => 'DEPRECATED, now controlled by ACLs. Used to enable unvoiding of voided payments', - 'type' => 'checkbox', - }, - { 'key' => 'address1-search', 'section' => 'UI', @@ -3404,12 +3337,6 @@ and customer address. Include units.', 'per_agent' => 1, }, - { 'key' => 'referral_credit', - 'section' => 'deprecated', - 'description' => "Used to enable one-time referral credits in the amount of one month referred 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.', @@ -3709,14 +3636,14 @@ and customer address. Include units.', { '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', }, @@ -3833,11 +3760,12 @@ and customer address. Include units.', 'select_enum' => [ 'approve', 'decline' ], }, + # replaces batch-errors_to (sent email on error) { - 'key' => 'batch-errors_to', + 'key' => 'batch-errors_not_fatal', 'section' => 'billing', - 'description' => 'Email errors when processing batches to this address. If unspecified, batch processing will stop immediately on error.', - 'type' => 'text', + 'description' => 'If checked, when importing batches from a gateway, item errors will be recorded in the system log without aborting processing. If unchecked, batch processing will fail on error.', + 'type' => 'checkbox', }, #lists could be auto-generated from pay_batch info @@ -3906,7 +3834,14 @@ and customer address. Include units.', { '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', }, @@ -3946,6 +3881,13 @@ and customer address. Include units.', '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', @@ -4349,8 +4291,22 @@ and customer address. Include units.', { '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', }, { @@ -4386,6 +4342,7 @@ and customer address. Include units.', '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', }, { @@ -4473,6 +4430,13 @@ and customer address. Include units.', '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', @@ -4483,7 +4447,7 @@ and customer address. Include units.', { '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() ], @@ -4666,13 +4630,6 @@ and customer address. Include units.', 'type' => 'text', }, - { - 'key' => 'email_report-subject', - 'section' => '', - 'description' => 'Subject for reports emailed by freeside-fetch. Defaults to "Freeside report".', - 'type' => 'text', - }, - { 'key' => 'selfservice-head', 'section' => 'self-service', @@ -5244,7 +5201,7 @@ and customer address. Include units.', { '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', }, @@ -5258,7 +5215,7 @@ and customer address. Include units.', { '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', @@ -5286,7 +5243,7 @@ and customer address. Include units.', { 'key' => 'enable_tax_adjustments', - 'section' => 'billing', + 'section' => 'taxation', 'description' => 'Enable the ability to add manual tax adjustments.', 'type' => 'checkbox', }, @@ -5739,7 +5696,7 @@ and customer address. Include units.', { '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', }, @@ -5774,6 +5731,13 @@ and customer address. Include units.', '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', @@ -5792,13 +5756,6 @@ and customer address. Include units.', ], }, - { - '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', @@ -5927,47 +5884,21 @@ and customer address. Include units.', 'type' => 'checkbox', }, - { key => "apacheroot", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "apachemachine", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "apachemachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "bindprimary", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "bindsecondaries", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "bsdshellmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "cyrus", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "cp_app", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "erpcdmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "icradiusmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "icradius_mysqldest", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "icradius_mysqlsource", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "icradius_secrets", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "maildisablecatchall", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "mxmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "nsmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "arecords", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "cnamerecords", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "nismachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "qmailmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "radiusmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "sendmailconfigpath", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "sendmailmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "sendmailrestart", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "shellmachine", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "shellmachine-useradd", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "shellmachine-userdel", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "shellmachine-usermod", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "shellmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "radiusprepend", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "textradiusprepend", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "username_policy", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "vpopmailmachines", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "vpopmailrestart", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "safe-part_pkg", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "selfservice_server-quiet", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "signup_server-quiet", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "signup_server-email", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "vonage-username", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "vonage-password", section => "deprecated", description => "DEPRECATED", type => "text" }, - { key => "vonage-fromnumber", section => "deprecated", description => "DEPRECATED", 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', + #}, );