X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FConf.pm;h=90b5d2985c619957947c006ef365728e43c921b2;hb=1e64160a779e96d84c5db648622dee4f88f34215;hp=c5c03ff08146dc20edbc6fc2d0067995408a6d2d;hpb=fb3f24328beb8e4d8703ea0d5376cdaaa86533a0;p=freeside.git diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index c5c03ff08..90b5d2985 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -11,12 +11,11 @@ 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%%%'; @@ -113,14 +112,6 @@ 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 }; @@ -155,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; @@ -179,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) : ''; @@ -194,7 +183,6 @@ is undefined. sub exists { my $self = shift; - return $self->_usecompat('exists', @_) if use_confcompat; #my($name, $agentnum)=@_; @@ -209,7 +197,6 @@ sub exists { sub config_bool { my $self = shift; - return $self->_usecompat('exists', @_) if use_confcompat; my($name,$agentnum,$agentonly) = @_; @@ -264,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") ) { @@ -284,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") ) { @@ -327,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) ) { @@ -348,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; @@ -393,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); @@ -407,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}}) ) { @@ -434,7 +415,6 @@ sub delete { sub delete_bool { my $self = shift; - return $self->_usecompat('delete', @_) if use_confcompat; my($name, $agentnum) = @_; @@ -465,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"); @@ -474,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 @@ -606,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(@_) ); } @@ -642,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 } @@ -697,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 ); @@ -795,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) @@ -1286,10 +1201,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, }, { @@ -1396,6 +1308,15 @@ sub reason_type_options { }, { + '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', 'description' => 'Optional LaTeX template for typeset PostScript invoices. See the billing documentation for details.', @@ -1583,6 +1504,15 @@ and customer address. Include units.', }, { + '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', 'description' => 'Send PDF invoice as an attachment to emailed invoices. By default, includes the HTML invoice as the email body, unless invoice_email_pdf_note is set.', @@ -2387,6 +2317,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', ], }, @@ -2543,65 +2474,107 @@ 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', 'description' => 'Template to use for welcome messages when a svc_acct record is created.', %msg_template_options, }, - + + { 'key' => 'svc_acct_welcome_letter', + 'section' => 'notification', + 'description' => 'Optional LaTex template for a printed welcome letter when a svc_acct record is created. Fields from the customer and svc_acct records are available for substitution.', + 'type' => 'textarea', + }, + { 'key' => 'svc_acct_welcome_exclude', 'section' => 'notification', - 'description' => 'A list of svc_acct services for which no welcome email is to be sent.', + 'description' => 'A list of svc_acct services for which no welcome email or letter is to be sent.', 'type' => 'select-part_svc', 'multiple' => 1, }, @@ -2793,6 +2766,14 @@ and customer address. Include units.', }, { + 'key' => 'dump-email_to', + 'section' => '', + 'description' => "Optional email address to send success/failure message for database dumps.", + 'type' => 'text', + 'validate' => $validate_email, + }, + + { '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.', @@ -3408,14 +3389,6 @@ and customer address. Include units.', }, { - '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', @@ -3770,14 +3743,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', }, @@ -4008,6 +3981,13 @@ and customer address. Include units.', }, { + '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', '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.', @@ -4410,8 +4390,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', }, { @@ -4536,6 +4530,13 @@ and customer address. Include units.', }, { + 'key' => 'cust_main-no_city_in_address', + 'section' => 'UI', + 'description' => 'Turn off City for billing & shipping addresses', + 'type' => 'checkbox', + }, + + { 'key' => 'census_year', 'section' => 'UI', 'description' => 'The year to use in census tract lookups. NOTE: you need to select 2012 or 2013 for Year 2010 Census tract codes. A selection of 2011 provides Year 2000 Census tract codes. Use the freeside-censustract-update tool if exisitng customers need to be changed.', @@ -4545,7 +4546,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() ], @@ -5306,7 +5307,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', }, @@ -5320,7 +5321,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', @@ -5348,7 +5349,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', }, @@ -5801,7 +5802,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', }, @@ -5837,6 +5838,13 @@ and customer address. Include units.', }, { + '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', 'description' => 'If set, automatically log users out of the backoffice after this many minutes.', @@ -5989,6 +5997,13 @@ and customer address. Include units.', 'type' => 'checkbox', }, + { + 'key' => 'default_appointment_length', + 'section' => 'UI', + 'description' => 'Default appointment length, in minutes (30 minute granularity).', + 'type' => 'text', + }, + { key => "apacheroot", section => "deprecated", description => "DEPRECATED", type => "text" }, { key => "apachemachine", section => "deprecated", description => "DEPRECATED", type => "text" }, { key => "apachemachines", section => "deprecated", description => "DEPRECATED", type => "text" },