package FS::Conf;
-use vars qw($base_dir @config_items @card_types $DEBUG );
+use vars qw($base_dir @config_items @base_items @card_types $DEBUG);
+use Carp;
+use IO::File;
+use File::Basename;
use MIME::Base64;
use FS::ConfItem;
use FS::ConfDefaults;
+use FS::Conf_compat17;
use FS::conf;
use FS::Record qw(qsearch qsearchs);
-use FS::UID qw(dbh);
+use FS::UID qw(dbh datasrc use_confcompat);
$base_dir = '%%%FREESIDE_CONF%%%';
-
$DEBUG = 0;
=head1 NAME
$1;
}
-=item config KEY
+=item config KEY [ AGENTNUM ]
Returns the configuration value or values (depending on context) for key.
+The optional agent number selects an agent specific value instead of the
+global default if one is present.
=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,$agent)=@_;
+ my($self,$name,$agentnum)=@_;
my $hashref = { 'name' => $name };
- if (defined($agent) && $agent) {
- $hashref->{agent} = $agent;
- }
+ $hashref->{agentnum} = $agentnum;
local $FS::Record::conf = undef; # XXX evil hack prevents recursion
my $cv = FS::Record::qsearchs('conf', $hashref);
- if (!$cv && exists($hashref->{agent})) {
- delete($hashref->{agent});
+ if (!$cv && defined($agentnum)) {
+ $hashref->{agentnum} = '';
$cv = FS::Record::qsearchs('conf', $hashref);
}
return $cv;
}
sub config {
- my($self,$name,$agent)=@_;
- my $cv = $self->_config($name, $agent) or return;
+ my $self = shift;
+ return $self->_usecompat('config', @_) if use_confcompat;
+
+ my($name,$agentnum)=@_;
+ my $cv = $self->_config($name, $agentnum) or return;
if ( wantarray ) {
- split "\n", $cv->value;
+ my $v = $cv->value;
+ chomp $v;
+ (split "\n", $v, -1);
} else {
(split("\n", $cv->value))[0];
}
}
-=item config_binary KEY
+=item config_binary KEY [ AGENTNUM ]
Returns the exact scalar value for key.
=cut
sub config_binary {
- my($self,$name,$agent)=@_;
- my $cv = $self->_config($name, $agent) or return;
+ my $self = shift;
+ return $self->_usecompat('config_binary', @_) if use_confcompat;
+
+ my($name,$agentnum)=@_;
+ my $cv = $self->_config($name, $agentnum) or return;
decode_base64($cv->value);
}
-=item exists KEY
+=item exists KEY [ AGENTNUM ]
Returns true if the specified key exists, even if the corresponding value
is undefined.
=cut
sub exists {
- my($self,$name,$agent)=@_;
- defined($self->_config($name, $agent));
+ my $self = shift;
+ return $self->_usecompat('exists', @_) if use_confcompat;
+
+ my($name,$agentnum)=@_;
+ defined($self->_config($name, $agentnum));
}
=item config_orbase KEY SUFFIX
=cut
+# outmoded as soon as we shift to agentnum based config values
+# well, mostly. still useful for e.g. late notices, etc. in that we want
+# these to fall back to standard values
sub config_orbase {
- my( $self, $name, $suffix ) = @_;
+ my $self = shift;
+ return $self->_usecompat('config_orbase', @_) if use_confcompat;
+
+ my( $name, $suffix ) = @_;
if ( $self->exists("${name}_$suffix") ) {
$self->config("${name}_$suffix");
} else {
}
}
-=item touch KEY
+=item key_orbase KEY SUFFIX
+
+If the config value KEY_SUFFIX exists, returns KEY_SUFFIX, otherwise returns
+KEY. Useful for determining which exact configuration option is returned by
+config_orbase.
+
+=cut
+
+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") ) {
+ "${name}_$suffix";
+ } else {
+ $name;
+ }
+}
+
+=item invoice_templatenames
+
+Returns all possible invoice template names.
+
+=cut
+
+sub invoice_templatenames {
+ my( $self ) = @_;
+
+ my %templatenames = ();
+ foreach my $item ( $self->config_items ) {
+ foreach my $base ( @base_items ) {
+ my( $main, $ext) = split(/\./, $base);
+ $ext = ".$ext" if $ext;
+ if ( $item->key =~ /^${main}_(.+)$ext$/ ) {
+ $templatenames{$1}++;
+ }
+ }
+ }
+
+ sort keys %templatenames;
+
+}
+
+=item touch KEY [ AGENT ];
Creates the specified configuration key if it does not exist.
=cut
sub touch {
- my($self, $name, $agent) = @_;
- $self->set($name, '', $agent);
+ my $self = shift;
+ return $self->_usecompat('touch', @_) if use_confcompat;
+
+ my($name, $agentnum) = @_;
+ unless ( $self->exists($name, $agentnum) ) {
+ $self->set($name, '', $agentnum);
+ }
}
-=item set KEY VALUE
+=item set KEY VALUE [ AGENTNUM ];
Sets the specified configuration key to the given value.
=cut
sub set {
- my($self, $name, $value, $agent) = @_;
+ my $self = shift;
+ return $self->_usecompat('set', @_) if use_confcompat;
+
+ my($name, $value, $agentnum) = @_;
$value =~ /^(.*)$/s;
$value = $1;
- warn "[FS::Conf] SET $file\n" if $DEBUG;
+ warn "[FS::Conf] SET $name\n" if $DEBUG;
- my $old = FS::Record::qsearchs('conf', {name => $name, agent => $agent});
+ my $old = FS::Record::qsearchs('conf', {name => $name, agentnum => $agentnum});
my $new = new FS::conf { $old ? $old->hash
- : ('name' => $name, 'agent' => $agent)
+ : ('name' => $name, 'agentnum' => $agentnum)
};
$new->value($value);
}
-=item set_binary KEY VALUE
+=item set_binary KEY VALUE [ AGENTNUM ]
Sets the specified configuration key to an exact scalar value which
can be retrieved with config_binary.
=cut
sub set_binary {
- my($self,$name, $value, $agent)=@_;
- $self->set($name, encode_base64($value), $agent);
+ my $self = shift;
+ return if use_confcompat;
+
+ my($name, $value, $agentnum)=@_;
+ $self->set($name, encode_base64($value), $agentnum);
}
-=item delete KEY
+=item delete KEY [ AGENTNUM ];
Deletes the specified configuration key.
=cut
sub delete {
- my($self, $name, $agent) = @_;
- if ( my $cv = FS::Record::qsearchs('conf', {name => $name, agent => $agent}) ) {
- warn "[FS::Conf] DELETE $file\n";
+ my $self = shift;
+ return $self->_usecompat('delete', @_) if use_confcompat;
+
+ my($name, $agentnum) = @_;
+ if ( my $cv = FS::Record::qsearchs('conf', {name => $name, agentnum => $agentnum}) ) {
+ warn "[FS::Conf] DELETE $name\n";
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
}
}
+=item import_config_item CONFITEM DIR
+
+ Imports the item specified by the CONFITEM (see L<FS::ConfItem>) into
+the database as a conf record (see L<FS::conf>). Imports from the file
+in the directory DIR.
+
+=cut
+
+sub import_config_item {
+ my ($self,$item,$dir) = @_;
+ my $key = $item->key;
+ if ( -e "$dir/$key" && ! use_confcompat ) {
+ warn "Inserting $key\n" if $DEBUG;
+ local $/;
+ my $value = readline(new IO::File "$dir/$key");
+ if ($item->type eq 'binary') {
+ $self->set_binary($key, $value);
+ }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);
+
+ unless ($type eq 'binary') {
+ {
+ 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;
+ }
+ }
+
+ if ($type eq 'binary') {
+ $error .= "$key fails binary comparison; "
+ unless scalar($self->config_binary($key)) eq scalar($compat->config_binary($key));
+ }
+
+ 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
+#
+#Returns all of the possible extensible config items as FS::ConfItem objects.
+#See #L<FS::ConfItem>. OPTIONS consists of name value pairs. Possible
+#options include
+#
+# dir - the directory to search for configuration option files instead
+# of using the conf records in the database
+#
+#cut
+
+#quelle kludge
+sub _orbase_items {
+ my ($self, %opt) = @_;
+
+ my $listmaker = sub { my $v = shift;
+ $v =~ s/_/!_/g;
+ if ( $v =~ /\.(png|eps)$/ ) {
+ $v =~ s/\./!_%./;
+ }else{
+ $v .= '!_%';
+ }
+ map { $_->name }
+ FS::Record::qsearch( 'conf',
+ {},
+ '',
+ "WHERE name LIKE '$v' ESCAPE '!'"
+ );
+ };
+
+ if (exists($opt{dir}) && $opt{dir}) {
+ $listmaker = sub { my $v = shift;
+ if ( $v =~ /\.(png|eps)$/ ) {
+ $v =~ s/\./_*./;
+ }else{
+ $v .= '_*';
+ }
+ map { basename $_ } glob($opt{dir}. "/$v" );
+ };
+ }
+
+ ( map {
+ my $proto;
+ my $base = $_;
+ for ( @config_items ) { $proto = $_; last if $proto->key eq $base; }
+ die "don't know about $base items" unless $proto->key eq $base;
+
+ map { new FS::ConfItem {
+ 'key' => $_,
+ 'section' => $proto->section,
+ 'description' => 'Alternate ' . $proto->description . ' See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Invoice_templates">billing documentation</a> for details.',
+ 'type' => $proto->type,
+ };
+ } &$listmaker($base);
+ } @base_items,
+ );
+}
+
=item config_items
-Returns all of the possible configuration items as FS::ConfItem objects. See
-L<FS::ConfItem>.
+Returns all of the possible global/default configuration items as
+FS::ConfItem objects. See L<FS::ConfItem>.
=cut
sub config_items {
my $self = shift;
- #quelle kludge
- @config_items,
- ( map {
- new FS::ConfItem {
- 'key' => $_->name,
- 'section' => 'billing',
- 'description' => 'Alternate template file for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
- 'type' => 'textarea',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_template!_%' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => '$_->name',
- 'section' => 'billing', #?
- 'description' => 'An image to include in some types of invoices',
- 'type' => 'binary',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'logo!_%.png' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => $_->name,
- 'section' => 'billing',
- 'description' => 'Alternate HTML template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
- 'type' => 'textarea',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_html!_%' ESCAPE '!'")
- ),
- ( map {
- ($latexname = $_->name ) =~ s/latex/html/;
- new FS::ConfItem {
- 'key' => $_->name,
- 'section' => 'billing',
- 'description' => "Alternate Notes section for HTML invoices. Defaults to the same data in $latexname if not specified.",
- 'type' => 'textarea',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_htmlnotes!_%' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => $_->name,
- 'section' => 'billing',
- 'description' => 'Alternate LaTeX template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
- 'type' => 'textarea',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_latex!_%' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => '$_->name',
- 'section' => 'billing', #?
- 'description' => 'An image to include in some types of invoices',
- 'type' => 'binary',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'logo!_%.eps' ESCAPE '!'")
- ),
- ( map {
- new FS::ConfItem {
- 'key' => $_->name,
- 'section' => 'billing',
- 'description' => 'Alternate Notes section for LaTeX typeset PostScript invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
- 'type' => 'textarea',
- }
- } FS::Record::qsearch('conf', {}, '', "WHERE name LIKE 'invoice!_latexnotes!_%' ESCAPE '!'")
- );
+ return $self->_usecompat('config_items', @_) if use_confcompat;
+
+ ( @config_items, $self->_orbase_items(@_) );
+}
+
+=back
+
+=head1 SUBROUTINES
+
+=over 4
+
+=item init-config DIR
+
+Imports the non-deprecated configuration items from DIR (1.7 compatible)
+to conf records in the database.
+
+=cut
+
+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;
+ }
+ }
+
+ $FS::UID::use_confcompat = 0;
+ ''; #success
}
=back
"Configuration" in the web interface (config/config.cgi).
-httemplate/docs/config.html
-
=cut
#Business::CreditCard
"Solo",
);
+@base_items = qw (
+ invoice_template
+ invoice_latex
+ invoice_latexreturnaddress
+ invoice_latexfooter
+ invoice_latexsmallfooter
+ invoice_latexnotes
+ invoice_latexcoupon
+ invoice_html
+ invoice_htmlreturnaddress
+ invoice_htmlfooter
+ invoice_htmlnotes
+ logo.png
+ logo.eps
+ );
+
@config_items = map { new FS::ConfItem $_ } (
{
{
'key' => 'alerter_template',
'section' => 'billing',
- 'description' => 'Template file for billing method expiration alerts. See the <a href="../docs/billing.html#invoice_template">billing documentation</a> for details.',
+ 'description' => 'Template file for billing method expiration alerts. See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Credit_cards_and_Electronic_checks">billing documentation</a> for details.',
'type' => 'textarea',
},
'type' => 'text',
},
+ {
+ 'key' => 'business-onlinepayment-email_customer',
+ 'section' => 'billing',
+ 'description' => 'Controls the "email_customer" flag used by some Business::OnlinePayment processors to enable customer receipts.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'countrydefault',
'section' => 'UI',
{
'key' => 'home',
- 'section' => 'required',
+ 'section' => 'shell',
'description' => 'For new users, prefixed to username to create a directory name. Should have a leading but not a trailing slash.',
'type' => 'text',
},
{
'key' => 'invoice_template',
- 'section' => 'required',
- 'description' => 'Required template file for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
+ 'section' => 'billing',
+ 'description' => 'Text template file for invoices. Used if no invoice_html template is defined, and also seen by users using non-HTML capable mail clients. See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Plaintext_invoice_templates">billing documentation</a> for details.',
'type' => 'textarea',
},
{
'key' => 'invoice_html',
'section' => 'billing',
- 'description' => 'Optional HTML template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
+ 'description' => 'Optional HTML template for invoices. See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#HTML_invoice_templates">billing documentation</a> for details.',
'type' => 'textarea',
},
{
'key' => 'invoice_latex',
'section' => 'billing',
- 'description' => 'Optional LaTeX template for typeset PostScript invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
+ 'description' => 'Optional LaTeX template for typeset PostScript invoices. See the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Administration#Typeset_.28LaTeX.29_invoice_templates">billing documentation</a> for details.',
'type' => 'textarea',
},
'type' => 'textarea',
},
+ {
+ 'key' => 'invoice_latexcoupon',
+ 'section' => 'billing',
+ 'description' => 'Remittance coupon for LaTeX typeset PostScript invoices.',
+ 'type' => 'textarea',
+ },
+
{
'key' => 'invoice_latexreturnaddress',
'section' => 'billing',
'section' => 'billing',
'description' => 'Optional default invoice term, used to calculate a due date printed on invoices.',
'type' => 'select',
- 'select_enum' => [ '', 'Payable upon receipt', 'Net 0', 'Net 10', 'Net 15', 'Net 30', 'Net 45', 'Net 60' ],
+ 'select_enum' => [ '', 'Payable upon receipt', 'Net 0', 'Net 10', 'Net 15', 'Net 20', 'Net 30', 'Net 45', 'Net 60' ],
+ },
+
+ {
+ 'key' => 'invoice_sections',
+ 'section' => 'billing',
+ 'description' => 'Split invoice into sections and label according to package class when enabled.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'separate_usage',
+ 'section' => 'billing',
+ 'description' => 'Split the rated call usage into a separate line from the recurring charges.',
+ 'type' => 'checkbox',
},
{
'key' => 'payment_receipt_email',
'section' => 'billing',
- 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received. See the <a href="http://search.cpan.org/~mjd/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <ul><li><code>$date</code> <li><code>$name</code> <li><code>$paynum</code> - Freeside payment number <li><code>$paid</code> - Amount of payment <li><code>$payby</code> - Payment type (Card, Check, Electronic check, etc.) <li><code>$payinfo</code> - Masked credit card number or check number <li><code>$balance</code> - New balance</ul>',
+ 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <ul><li><code>$date</code> <li><code>$name</code> <li><code>$paynum</code> - Freeside payment number <li><code>$paid</code> - Amount of payment <li><code>$payby</code> - Payment type (Card, Check, Electronic check, etc.) <li><code>$payinfo</code> - Masked credit card number or check number <li><code>$balance</code> - New balance</ul>',
'type' => [qw( checkbox textarea )],
},
'type' => 'text',
},
+ {
+ 'key' => 'lpr-postscript_prefix',
+ 'section' => 'billing',
+ 'description' => 'Raw printer commands prepended to the beginning of postscript print jobs (evaluated as a double-quoted perl string - backslash escapes are available)',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'lpr-postscript_suffix',
+ 'section' => 'billing',
+ 'description' => 'Raw printer commands added to the end of postscript print jobs (evaluated as a double-quoted perl string - backslash escapes are available)',
+ 'type' => 'text',
+ },
+
{
'key' => 'money_char',
'section' => '',
{
'key' => 'shells',
- 'section' => 'required',
+ 'section' => 'shell',
'description' => 'Legal shells (think /etc/shells). You probably want to `cut -d: -f7 /etc/passwd | sort | uniq\' initially so that importing doesn\'t fail with `Illegal shell\' errors, then remove any special entries afterwords. A blank line specifies that an empty shell is permitted.',
'type' => 'textarea',
},
{
'key' => 'signupurl',
'section' => 'UI',
- 'description' => 'if you are using customer-to-customer referrals, and you enter the URL of your <a href="../docs/signup.html">signup server CGI</a>, the customer view screen will display a customized link to the signup server with the appropriate customer as referral',
+ 'description' => 'if you are using customer-to-customer referrals, and you enter the URL of your <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:Self-Service_Installation">signup server CGI</a>, the customer view screen will display a customized link to the signup server with the appropriate customer as referral',
'type' => 'text',
},
{
'key' => 'username-uppercase',
'section' => 'username',
- 'description' => 'Allow uppercase characters in usernames',
+ 'description' => 'Allow uppercase characters in usernames. Not recommended for use with FreeRADIUS with MySQL backend, which is case-insensitive by default.',
'type' => 'checkbox',
},
'type' => 'checkbox',
},
+ {
+ '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.",
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'agent_defaultpkg',
'section' => 'UI',
{
'key' => 'signup_server-default_pkgpart',
'section' => '',
- 'description' => 'Default pakcage for the signup server',
+ 'description' => 'Default package for the signup server',
'type' => 'select-sub',
'options_sub' => sub { require FS::Record;
require FS::part_pkg;
},
},
+ {
+ 'key' => 'signup_server-default_svcpart',
+ 'section' => '',
+ 'description' => 'Default svcpart for the signup server - only necessary for services that trigger special provisioning widgets (such as DID provisioning).',
+ 'type' => 'select-sub',
+ 'options_sub' => sub { require FS::Record;
+ require FS::part_svc;
+ map { $_->svcpart => $_->svc }
+ FS::Record::qsearch( 'part_svc',
+ { 'disabled' => ''}
+ );
+ },
+ 'option_sub' => sub { require FS::Record;
+ require FS::part_svc;
+ my $part_svc = FS::Record::qsearchs(
+ 'part_svc', { 'svcpart'=>shift }
+ );
+ $part_svc ? $part_svc->svc : '';
+ },
+ },
+
+ {
+ 'key' => 'signup_server-service',
+ 'section' => '',
+ 'description' => 'Service for the signup server - "Account (svc_acct)" is the default setting, or "Phone number (svc_phone)" for ITSP signup',
+ 'type' => 'select',
+ 'select_hash' => [
+ 'svc_acct' => 'Account (svc_acct)',
+ 'svc_phone' => 'Phone number (svc_phone)',
+ ],
+ },
+
+ {
+ 'key' => 'selfservice_server-base_url',
+ 'section' => '',
+ 'description' => 'Base URL for the self-service web interface - necessary for special provisioning widgets to find their way.',
+ 'type' => 'text',
+ },
+
{
'key' => 'show-msgcat-codes',
'section' => 'UI',
{
'key' => 'emailcancel',
'section' => 'billing',
- 'description' => 'Enable emailing of cancellation notices.',
+ 'description' => 'Enable emailing of cancellation notices. Make sure to fill in the cancelmessage and cancelsubject configuration values as well.',
'type' => 'checkbox',
},
'type' => 'checkbox',
},
+ {
+ 'key' => 'enable_taxproducts',
+ 'section' => 'billing',
+ 'description' => 'Enable per-package mapping to new style tax classes',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'welcome_email',
'section' => '',
- 'description' => 'Template file for welcome email. Welcome emails are sent to the customer email invoice destination(s) each time a svc_acct record is created. See the <a href="http://search.cpan.org/~mjd/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code></ul>',
+ 'description' => 'Template file for welcome email. Welcome emails are sent to the customer email invoice destination(s) each time a svc_acct record is created. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code></ul>',
'type' => 'textarea',
+ 'per_agent' => 1,
},
{
'section' => '',
'description' => 'From: address header for welcome email',
'type' => 'text',
+ 'per_agent' => 1,
},
{
'section' => '',
'description' => 'Subject: header for welcome email',
'type' => 'text',
+ 'per_agent' => 1,
},
{
'description' => 'MIME type for welcome email',
'type' => 'select',
'select_enum' => [ 'text/plain', 'text/html' ],
+ 'per_agent' => 1,
+ },
+
+ {
+ 'key' => 'welcome_letter',
+ 'section' => '',
+ 'description' => 'Optional LaTex template file for a printed welcome letter. A welcome letter is printed the first time a cust_pkg record is created. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation and the billing documentation for details on the template substitution language. A variable exists for each fieldname in the customer record (<code>$first, $last, etc</code>). The following additional variables are available<ul><li><code>$payby</code> - a friendler represenation of the field<li><code>$payinfo</code> - the masked payment information<li><code>$expdate</code> - the time at which the payment method expires (a UNIX timestamp)<li><code>$returnaddress</code> - the invoice return address for this customer\'s agent</ul>',
+ 'type' => 'textarea',
},
{
'key' => 'warning_email',
'section' => '',
- 'description' => 'Template file for warning email. Warning emails are sent to the customer email invoice destination(s) each time a svc_acct record has its usage drop below a threshold or 0. See the <a href="http://search.cpan.org/~mjd/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code> <li><code>$column</code> <li><code>$amount</code> <li><code>$threshold</code></ul>',
+ 'description' => 'Template file for warning email. Warning emails are sent to the customer email invoice destination(s) each time a svc_acct record has its usage drop below a threshold or 0. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code> <li><code>$column</code> <li><code>$amount</code> <li><code>$threshold</code></ul>',
'type' => 'textarea',
},
'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP HIDE) ],
},
+ {
+ 'key' => 'paymentforcedtobatch',
+ 'section' => 'UI',
+ 'description' => 'Causes per customer payment entry to be forced to a batch processor rather than performed realtime.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'svc_acct-notes',
'section' => 'UI',
'type' => 'checkbox',
},
+ {
+ 'key' => 'selfservice_server-phone_login',
+ 'section' => '',
+ 'description' => 'Allow login to self-service with phone number and PIN.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'card_refund-days',
'section' => 'billing',
{
'key' => 'ticket_system',
'section' => '',
- 'description' => 'Ticketing system integration. <b>RT_Internal</b> uses the built-in RT ticketing system (see the <a href="../docs/install-rt">integrated ticketing installation instructions</a>). <b>RT_External</b> accesses an external RT installation in a separate database (local or remote).',
+ 'description' => 'Ticketing system integration. <b>RT_Internal</b> uses the built-in RT ticketing system (see the <a href="http://www.freeside.biz/mediawiki/index.php/Freeside:1.7:Documentation:RT_Installation">integrated ticketing installation instructions</a>). <b>RT_External</b> accesses an external RT installation in a separate database (local or remote).',
'type' => 'select',
#'select_enum' => [ '', qw(RT_Internal RT_Libs RT_External) ],
'select_enum' => [ '', qw(RT_Internal RT_External) ],
},
},
+ {
+ 'key' => 'ticket_system-priority_reverse',
+ 'section' => '',
+ 'description' => 'Enable this to consider lower numbered priorities more important. A bad habit we picked up somewhere. You probably want to avoid it and use the default.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'ticket_system-custom_priority_field',
'section' => '',
'type' => 'text',
},
+ {
+ 'key' => 'company_address',
+ 'section' => 'required',
+ 'description' => 'Your company address',
+ 'type' => 'textarea',
+ },
+
{
'key' => 'address2-search',
'section' => 'UI',
- 'description' => 'Enable a "Unit" search box which searches the second address field',
+ 'description' => 'Enable a "Unit" search box which searches the second address field. Useful for multi-tenant applications. See also: cust_main-require_address2',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_main-require_address2',
+ 'section' => 'UI',
+ 'description' => 'Second address field is required (on service address only, if billing and service addresses differ). Also enables "Unit" labeling of address2 on customer view and edit pages. Useful for multi-tenant applications. See also: address2-search',
'type' => 'checkbox',
},
{
'key' => 'hylafax',
- 'section' => '',
+ 'section' => 'billing',
'description' => 'Options for a HylaFAX server to enable the FAX invoice destination. They should be in the form of a space separated list of arguments to the Fax::Hylafax::Client::sendfax subroutine. You probably shouldn\'t override things like \'docfile\'. *Note* Only supported when using typeset invoices (see the invoice_latex configuration option).',
'type' => [qw( checkbox textarea )],
},
+ {
+ 'key' => 'cust_bill-ftpformat',
+ 'section' => 'billing',
+ 'description' => 'Enable FTP of raw invoice data - format.',
+ 'type' => 'select',
+ 'select_enum' => [ '', 'default', 'billco', ],
+ },
+
+ {
+ 'key' => 'cust_bill-ftpserver',
+ 'section' => 'billing',
+ 'description' => 'Enable FTP of raw invoice data - server.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_bill-ftpusername',
+ 'section' => 'billing',
+ 'description' => 'Enable FTP of raw invoice data - server.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_bill-ftppassword',
+ 'section' => 'billing',
+ 'description' => 'Enable FTP of raw invoice data - server.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_bill-ftpdir',
+ 'section' => 'billing',
+ 'description' => 'Enable FTP of raw invoice data - server.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_bill-spoolformat',
+ 'section' => 'billing',
+ 'description' => 'Enable spooling of raw invoice data - format.',
+ 'type' => 'select',
+ 'select_enum' => [ '', 'default', 'billco', ],
+ },
+
+ {
+ 'key' => 'cust_bill-spoolagent',
+ 'section' => 'billing',
+ 'description' => 'Enable per-agent spooling of raw invoice data.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'svc_acct-usage_suspend',
'section' => 'billing',
'type' => 'checkbox',
},
+ {
+ 'key' => 'voip-cust_cdr_squelch',
+ 'section' => '',
+ 'description' => 'Enable the per-customer option for not printing CDR on invoices.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'svc_forward-arbitrary_dst',
'section' => '',
'type' => 'checkbox',
},
+ {
+ 'key' => 'invoice-ship_address',
+ 'section' => 'billing',
+ 'description' => 'Enable this switch to include the ship address on the invoice.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'invoice-unitprice',
+ 'section' => 'billing',
+ 'description' => 'This switch enables unit pricing on the invoice.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'postal_invoice-fee_pkgpart',
+ 'section' => 'billing',
+ 'description' => 'This allows selection of a package to insert on invoices for customers with postal invoices selected.',
+ 'type' => 'select-sub',
+ 'options_sub' => sub { require FS::Record;
+ require FS::part_pkg;
+ map { $_->pkgpart => $_->pkg }
+ FS::Record::qsearch('part_pkg', { disabled=>'' } );
+ },
+ 'option_sub' => sub { require FS::Record;
+ require FS::part_pkg;
+ my $part_pkg = FS::Record::qsearchs(
+ 'part_pkg', { 'pkgpart'=>shift }
+ );
+ $part_pkg ? $part_pkg->pkg : '';
+ },
+ },
+
{
'key' => 'batch-enable',
'section' => 'billing',
'select_enum' => \@card_types,
},
+ {
+ 'key' => 'disable-fuzzy',
+ 'section' => 'UI',
+ 'description' => 'Disable fuzzy searching. Speeds up searching for large sites, but only shows exact matches.',
+ 'type' => 'checkbox',
+ },
+
+ { 'key' => 'pkg_referral',
+ 'section' => '',
+ 'description' => 'Enable package-specific advertising sources.',
+ 'type' => 'checkbox',
+ },
+
+ { 'key' => 'pkg_referral-multiple',
+ 'section' => '',
+ 'description' => 'In addition, allow multiple advertising sources to be associated with a single package.',
+ 'type' => 'checkbox',
+ },
+
{
'key' => 'dashboard-toplist',
'section' => 'UI',
{
'key' => 'impending_recur_template',
'section' => 'billing',
- 'description' => 'Template file for alerts about looming first time recurrant billing. See the <a href="http://search.cpan.org/~mjd/Text-Template.pm">Text::Template</a> documentation for details on the template substitition language. Also see packages with a <a href="../browse/part_pkg.cgi">flat price plan</a> The following variables are available<ul><li><code>$packages</code> allowing <code>$packages->[0]</code> thru <code>$packages->[n]</code> <li><code>$package</code> the first package, same as <code>$packages->[0]</code> <li><code>$recurdates</code> allowing <code>$recurdates->[0]</code> thru <code>$recurdates->[n]</code> <li><code>$recurdate</code> the first recurdate, same as <code>$recurdate->[0]</code> <li><code>$first</code> <li><code>$last</code></ul>',
+ 'description' => 'Template file for alerts about looming first time recurrant billing. See the <a href="http://search.cpan.org/dist/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitition language. Also see packages with a <a href="../browse/part_pkg.cgi">flat price plan</a> The following variables are available<ul><li><code>$packages</code> allowing <code>$packages->[0]</code> thru <code>$packages->[n]</code> <li><code>$package</code> the first package, same as <code>$packages->[0]</code> <li><code>$recurdates</code> allowing <code>$recurdates->[0]</code> thru <code>$recurdates->[n]</code> <li><code>$recurdate</code> the first recurdate, same as <code>$recurdate->[0]</code> <li><code>$first</code> <li><code>$last</code></ul>',
# <li><code>$payby</code> <li><code>$expdate</code> most likely only confuse
'type' => 'textarea',
},
'type' => 'checkbox',
},
+ {
+ 'key' => 'selfservice-session_timeout',
+ 'section' => '',
+ 'description' => 'Self-service session timeout. Defaults to 1 hour.',
+ 'type' => 'select',
+ 'select_enum' => [ '1 hour', '2 hours', '4 hours', '8 hours', '1 day', '1 week', ],
+ },
+
{
'key' => 'disable_setup_suspended_pkgs',
'section' => 'billing',
'type' => 'checkbox',
},
+ {
+ 'key' => 'datavolume-forcemegabytes',
+ 'section' => 'UI',
+ 'description' => 'All data volumes are expressed in megabytes',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'datavolume-significantdigits',
+ 'section' => 'UI',
+ 'description' => 'number of significant digits to use to represent data volumes',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'disable_void_after',
+ 'section' => 'billing',
+ 'description' => 'Number of seconds after which freeside won\'t attempt to VOID a payment first when performing a refund.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'disable_line_item_date_ranges',
+ 'section' => 'billing',
+ 'description' => 'Prevent freeside from automatically generating date ranges on invoice line items.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ '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...
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'cust_main-require_phone',
+ 'section' => '',
+ 'description' => 'Require daytime or night for all customer records.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_main-require_invoicing_list_email',
+ 'section' => '',
+ 'description' => 'Email address field is required: require at least one invoicing email address for all customer records.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'svc_acct-display_paid_time_remaining',
+ 'section' => '',
+ 'description' => 'Show paid time remaining in addition to time remaining.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ '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 : '';
+ },
+ },
+
+ {
+ 'key' => 'referral_credit_type',
+ 'section' => 'billing',
+ 'description' => 'The group to use for new, automatically generated credit reasons resulting from referrals.',
+ '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 : '';
+ },
+ },
+
+ {
+ 'key' => 'signup_credit_type',
+ 'section' => 'billing',
+ '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 : '';
+ },
+ },
+
+ {
+ 'key' => 'cust_main-agent_custid-format',
+ 'section' => '',
+ 'description' => 'Enables searching of various formatted values in cust_main.agent_custid',
+ 'type' => 'select',
+ 'select_hash' => [
+ '' => 'Numeric only',
+ 'ww?d+' => 'Numeric with one or two letter prefix',
+ ],
+ },
+
+ {
+ 'key' => 'card_masking_method',
+ 'section' => 'UI',
+ 'description' => 'Digits to display when masking credit cards. Note that the first six digits are necessary to canonically identify the credit card type (Visa/MC, Amex, Discover, Maestro, etc.) in all cases. The first four digits can identify the most common credit card types in most cases (Visa/MC, Amex, and Discover). The first two digits can distinguish between Visa/MC and Amex. Note: You should manually remove stored paymasks if you change this value on an existing database, to avoid problems using stored cards.',
+ 'type' => 'select',
+ 'select_hash' => [
+ '' => '123456xxxxxx1234',
+ 'first6last2' => '123456xxxxxxxx12',
+ 'first4last4' => '1234xxxxxxxx1234',
+ 'first4last2' => '1234xxxxxxxxxx12',
+ 'first2last4' => '12xxxxxxxxxx1234',
+ 'first2last2' => '12xxxxxxxxxxxx12',
+ 'first0last4' => 'xxxxxxxxxxxx1234',
+ 'first0last2' => 'xxxxxxxxxxxxxx12',
+ ],
+ },
+
+ {
+ 'key' => 'disable_previous_balance',
+ 'section' => 'billing',
+ 'description' => 'Disable inclusion of previous balancem payment, and credit lines on invoices',
+ 'type' => 'checkbox',
+ },
+
+ {
+ '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.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'usps_webtools-password',
+ 'section' => 'UI',
+ 'description' => 'Production password for USPS web tools. Enables USPS address standardization. See <a href="http://www.usps.com/webtools/">USPS website</a>, register and agree not to use the tools for batch purposes.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_main-auto_standardize_address',
+ 'section' => 'UI',
+ 'description' => 'When using USPS web tools, automatically standardize the address without asking.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'disable_acl_changes',
+ 'section' => '',
+ 'description' => 'Disable all ACL changes, for demos.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_main-edit_agent_custid',
+ 'section' => 'UI',
+ 'description' => 'Enable editing of the agent_custid field.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'cust_main-default_areacode',
+ 'section' => 'UI',
+ 'description' => 'Default area code for customers.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'mcp_svcpart',
+ 'section' => '',
+ 'description' => 'Master Control Program svcpart. Leave this blank.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'cust_bill-max_same_services',
+ 'section' => 'billing',
+ 'description' => 'Maximum number of the same service to list individually on invoices before condensing to a single line listing the number of services. Defaults to 5.',
+ 'type' => 'text',
+ },
+
);
1;
-