summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
Diffstat (limited to 'FS')
-rw-r--r--FS/FS.pm6
-rw-r--r--FS/FS/CGI.pm14
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm159
-rw-r--r--FS/FS/ClientAPI/Signup.pm235
-rw-r--r--FS/FS/Conf.pm136
-rw-r--r--FS/FS/Record.pm85
-rw-r--r--FS/FS/UID.pm2
-rw-r--r--FS/FS/acct_snarf.pm128
-rwxr-xr-xFS/FS/addr_block.pm11
-rw-r--r--FS/FS/agent.pm26
-rw-r--r--FS/FS/cust_bill.pm519
-rw-r--r--FS/FS/cust_bill_pay.pm19
-rw-r--r--FS/FS/cust_credit.pm72
-rw-r--r--FS/FS/cust_credit_bill.pm40
-rw-r--r--FS/FS/cust_main.pm495
-rw-r--r--FS/FS/cust_main_county.pm32
-rw-r--r--FS/FS/cust_pay.pm14
-rw-r--r--FS/FS/cust_pay_batch.pm194
-rw-r--r--FS/FS/cust_pkg.pm69
-rw-r--r--FS/FS/cust_svc.pm111
-rw-r--r--FS/FS/part_bill_event.pm6
-rw-r--r--FS/FS/part_export.pm109
-rw-r--r--FS/FS/part_export/communigate_pro.pm144
-rw-r--r--FS/FS/part_export/communigate_pro_singledomain.pm11
-rw-r--r--FS/FS/part_export/domain_shellcommands.pm2
-rw-r--r--FS/FS/part_export/forward_shellcommands.pm2
-rw-r--r--FS/FS/part_export/postfix.pm7
-rw-r--r--FS/FS/part_export/router.pm166
-rw-r--r--FS/FS/part_export/shellcommands.pm15
-rw-r--r--FS/FS/part_export/www_shellcommands.pm2
-rw-r--r--FS/FS/part_pkg.pm30
-rw-r--r--FS/FS/part_referral.pm13
-rw-r--r--FS/FS/pkg_svc.pm11
-rw-r--r--FS/FS/raddb.pm1119
-rw-r--r--FS/FS/svc_Common.pm58
-rw-r--r--FS/FS/svc_acct.pm112
-rw-r--r--FS/FS/svc_domain.pm5
-rw-r--r--FS/FS/svc_external.pm174
-rw-r--r--FS/FS/svc_forward.pm40
-rw-r--r--FS/MANIFEST7
-rw-r--r--FS/bin/freeside-addoutsourceuser4
-rwxr-xr-xFS/bin/freeside-daily17
-rwxr-xr-xFS/bin/freeside-receivables-report217
-rw-r--r--FS/bin/freeside-selfservice-server55
-rwxr-xr-xFS/bin/freeside-setup54
-rw-r--r--FS/t/acct_snarf.t5
-rw-r--r--FS/t/svc_broadband.t5
-rw-r--r--FS/t/svc_external.t5
48 files changed, 3895 insertions, 867 deletions
diff --git a/FS/FS.pm b/FS/FS.pm
index e4a32082c..36c3a1777 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -54,6 +54,8 @@ L<FS::svc_Common> - Service base class
L<FS::svc_acct> - Account (shell, RADIUS, POP3) class
+L<FS::acct_snarf> - External mail account class
+
L<FS::radius_usergroup> - RADIUS groups
L<FS::svc_domain> - Domain class
@@ -64,6 +66,10 @@ L<FS::svc_forward> - Mail forwarding class
L<FS::svc_www> - Web virtual host class.
+L<FS::svc_broadband> - DSL, wireless and other broadband class.
+
+L<FS::svc_external> - Externally tracked service class.
+
L<FS::part_svc> - Service definition class
L<FS::part_svc_column> - Column constraint class
diff --git a/FS/FS/CGI.pm b/FS/FS/CGI.pm
index 86d20f6cb..905189e2e 100644
--- a/FS/FS/CGI.pm
+++ b/FS/FS/CGI.pm
@@ -44,8 +44,10 @@ Returns an HTML header.
=cut
sub header {
+ use Carp;
+ carp 'FS::CGI::header deprecated; include /elements/header.html instead';
+
my($title,$menubar,$etc)=@_; #$etc is for things like onLoad= etc.
- #use Carp;
$etc = '' unless defined $etc;
my $x = <<END;
@@ -107,6 +109,9 @@ Returns an HTML menubar.
=cut
sub menubar { #$menubar=menubar('Main Menu', '../', 'Item', 'url', ... );
+ use Carp;
+ carp 'FS::CGI::menubar deprecated; include /elements/menubar.html instead';
+
my($item,$url,@html);
while (@_) {
($item,$url)=splice(@_,0,2);
@@ -209,7 +214,9 @@ Returns current URL with LEVEL levels of path removed from the end (default 0).
sub popurl {
my($up)=@_;
my $cgi = &FS::UID::cgi;
- my $url = new URI::URL ( $cgi->isa('Apache') ? $cgi->uri : $cgi->url );
+ my $url_string = $cgi->isa('Apache') ? $cgi->uri : $cgi->url;
+ $url_string =~ s/\?.*//;
+ my $url = new URI::URL ( $url_string );
my(@path)=$url->path_components;
splice @path, 0-$up;
$url->path_components(@path);
@@ -225,6 +232,9 @@ Returns HTML tag for beginning a table.
=cut
sub table {
+ use Carp;
+ carp 'FS::CGI::table deprecated; include /elements/table.html instead';
+
my $col = shift;
if ( $col ) {
qq!<TABLE BGCOLOR="$col" BORDER=1 WIDTH="100%" CELLSPACING=0 CELLPADDING=2 BORDERCOLOR="#999999">!;
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index e12e93b12..445f0ece8 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -14,19 +14,35 @@ use FS::svc_domain;
use FS::cust_main;
use FS::cust_bill;
use FS::cust_main_county;
+use FS::cust_pkg;
use FS::ClientAPI; #hmm
FS::ClientAPI->register_handlers(
'MyAccount/login' => \&login,
'MyAccount/customer_info' => \&customer_info,
+ 'MyAccount/edit_info' => \&edit_info,
'MyAccount/invoice' => \&invoice,
'MyAccount/cancel' => \&cancel,
'MyAccount/payment_info' => \&payment_info,
'MyAccount/process_payment' => \&process_payment,
+ 'MyAccount/list_pkgs' => \&list_pkgs,
+ 'MyAccount/order_pkg' => \&order_pkg,
+ 'MyAccount/cancel_pkg' => \&cancel_pkg,
+ 'MyAccount/charge' => \&charge,
+);
+
+use vars qw( @cust_main_editable_fields );
+@cust_main_editable_fields = qw(
+ first last company address1 address2 city
+ county state zip country daytime night fax
+ ship_first ship_last ship_company ship_address1 ship_address2 ship_city
+ ship_state ship_zip ship_country ship_daytime ship_night ship_fax
);
#store in db?
-my $cache = new Cache::SharedMemoryCache();
+my $cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::MyAccount',
+} );
#false laziness w/FS::ClientAPI::passwd::passwd (needs to handle encrypted pw)
sub login {
@@ -100,6 +116,10 @@ sub customer_info {
$return{name} = $cust_main->first. ' '. $cust_main->get('last');
+ for (@cust_main_editable_fields) {
+ $return{$_} = $cust_main->get($_);
+ }
+
} else { #no customer record
my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $session->{'svcnum'} } )
@@ -115,6 +135,27 @@ sub customer_info {
}
+sub edit_info {
+ my $p = shift;
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'}
+ or return { 'error' => "no customer record" };
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ my $new = new FS::cust_main { $cust_main->hash };
+ $new->set( $_ => $p->{$_} )
+ foreach grep { exists $p->{$_} } @cust_main_editable_fields;
+ my $error = $new->replace($cust_main);
+ return { 'error' => $error } if $error;
+ #$cust_main = $new;
+
+ return { 'error' => '' };
+}
+
sub payment_info {
my $p = shift;
my $session = $cache->get($p->{'session_id'})
@@ -203,7 +244,7 @@ sub process_payment {
my $error = $cust_main->realtime_bop( 'CC', $p->{'amount'}, quiet=>1,
'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01',
map { $_ => $p->{$_} }
- qw( payname address1 address2 city state zip payinfo )
+ qw( payname address1 address2 city state zip payinfo paybatch )
);
return { 'error' => $error } if $error;
@@ -245,7 +286,7 @@ sub cancel {
my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
or return { 'error' => "unknown custnum $custnum" };
- my @errors = $cust_main->cancel;
+ my @errors = $cust_main->cancel( 'quiet'=>1 );
my $error = scalar(@errors) ? join(' / ', @errors) : '';
@@ -253,5 +294,117 @@ sub cancel {
}
+sub list_pkgs {
+ my $p = shift;
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ return { 'cust_pkg' => [ map { $_->hashref } $cust_main->ncancelled_pkgs ] };
+
+}
+
+sub order_pkg {
+ my $p = shift;
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ #false laziness w/ClientAPI/Signup.pm
+
+ my $cust_pkg = new FS::cust_pkg ( {
+ 'custnum' => $custnum,
+ 'pkgpart' => $p->{'pkgpart'},
+ } );
+ my $error = $cust_pkg->check;
+ return { 'error' => $error } if $error;
+
+ my $svc_acct = new FS::svc_acct ( {
+ 'svcpart' => $p->{'svcpart'} || $cust_pkg->part_pkg->svcpart('svc_acct'),
+ map { $_ => $p->{$_} }
+ qw( username _password sec_phrase popnum ),
+ } );
+
+ my @acct_snarf;
+ my $snarfnum = 1;
+ while ( length($p->{"snarf_machine$snarfnum"}) ) {
+ my $acct_snarf = new FS::acct_snarf ( {
+ 'machine' => $p->{"snarf_machine$snarfnum"},
+ 'protocol' => $p->{"snarf_protocol$snarfnum"},
+ 'username' => $p->{"snarf_username$snarfnum"},
+ '_password' => $p->{"snarf_password$snarfnum"},
+ } );
+ $snarfnum++;
+ push @acct_snarf, $acct_snarf;
+ }
+ $svc_acct->child_objects( \@acct_snarf );
+
+ my $y = $svc_acct->setdefault; # arguably should be in new method
+ return { 'error' => $y } if $y && !ref($y);
+
+ $error = $svc_acct->check;
+ return { 'error' => $error } if $error;
+
+ use Tie::RefHash;
+ tie my %hash, 'Tie::RefHash';
+ %hash = ( $cust_pkg => [ $svc_acct ] );
+ #msgcat
+ $error = $cust_main->order_pkgs( \%hash, '', 'noexport' => 1 );
+ return { 'error' => $error } if $error;
+
+ my $conf = new FS::Conf;
+ if ( $conf->exists('signup_server-realtime') ) {
+
+ my $old_balance = $cust_main->balance;
+
+ my $bill_error = $cust_main->bill;
+ $cust_main->apply_payments;
+ $cust_main->apply_credits;
+ $bill_error = $cust_main->collect;
+
+ if ( $cust_main->balance > $old_balance ) {
+ $cust_pkg->cancel('quiet'=>1);
+ return { 'error' => '_decline' };
+ } else {
+ $cust_pkg->reexport;
+ }
+
+ } else {
+ $cust_pkg->reexport;
+ }
+
+ return { error => '' };
+
+}
+
+sub cancel_pkg {
+ my $p = shift;
+ my $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
+
+ my $custnum = $session->{'custnum'};
+
+ my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
+ or return { 'error' => "unknown custnum $custnum" };
+
+ my $pkgnum = $session->{'pkgnum'};
+
+ my $cust_pkg = qsearchs('cust_pkg', { 'custnum' => $custnum,
+ 'pkgnum' => $pkgnum, } )
+ or return { 'error' => "unknown pkgnum $pkgnum" };
+
+ my $error = $cust_main->cancel( 'quiet'=>1 );
+ return { 'error' => $error };
+
+}
+
1;
diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm
new file mode 100644
index 000000000..375958b9c
--- /dev/null
+++ b/FS/FS/ClientAPI/Signup.pm
@@ -0,0 +1,235 @@
+package FS::ClientAPI::Signup;
+
+use strict;
+use Tie::RefHash;
+use FS::Conf;
+use FS::Record qw(qsearch qsearchs dbdef);
+use FS::agent;
+use FS::cust_main_county;
+use FS::part_pkg;
+use FS::svc_acct_pop;
+use FS::cust_main;
+use FS::cust_pkg;
+use FS::svc_acct;
+use FS::acct_snarf;
+use FS::Msgcat qw(gettext);
+
+use FS::ClientAPI; #hmm
+FS::ClientAPI->register_handlers(
+ 'Signup/signup_info' => \&signup_info,
+ 'Signup/new_customer' => \&new_customer,
+);
+
+sub signup_info {
+ #my $packet = shift;
+
+ my $conf = new FS::Conf;
+
+ use vars qw($signup_info); #cache for performance;
+ $signup_info ||= {
+
+ 'cust_main_county' =>
+ [ map { $_->hashref } qsearch('cust_main_county', {}) ],
+
+ 'agent' =>
+ [
+ map { $_->hashref }
+ qsearch('agent', dbdef->table('agent')->column('disabled')
+ ? { 'disabled' => '' }
+ : {}
+ )
+ ],
+
+ 'part_referral' =>
+ [
+ map { $_->hashref }
+ qsearch('part_referral',
+ dbdef->table('part_referral')->column('disabled')
+ ? { 'disabled' => '' }
+ : {}
+ )
+ ],
+
+ 'agentnum2part_pkg' =>
+ {
+ map {
+ my $href = $_->pkgpart_hashref;
+ $_->agentnum =>
+ [
+ map { { 'payby' => [ $_->payby ], %{$_->hashref} } }
+ grep { $_->svcpart('svc_acct') && $href->{ $_->pkgpart } }
+ qsearch( 'part_pkg', { 'disabled' => '' } )
+ ];
+ } qsearch('agent', dbdef->table('agent')->column('disabled')
+ ? { 'disabled' => '' }
+ : {}
+ )
+ },
+
+ 'svc_acct_pop' => [ map { $_->hashref } qsearch('svc_acct_pop',{} ) ],
+
+ 'security_phrase' => $conf->exists('security_phrase'),
+
+ 'payby' => [ $conf->config('signup_server-payby') ],
+
+ 'cvv_enabled' => defined dbdef->table('cust_main')->column('paycvv'),
+
+ 'msgcat' => { map { $_=>gettext($_) } qw(
+ passwords_dont_match invalid_card unknown_card_type not_a
+ ) },
+
+ 'statedefault' => $conf->config('statedefault') || 'CA',
+
+ 'countrydefault' => $conf->config('countrydefault') || 'US',
+
+ 'refnum' => $conf->config('signup_server-default_refnum'),
+
+ };
+
+ if (
+ $conf->config('signup_server-default_agentnum')
+ && !exists $signup_info->{'part_pkg'} #cache for performance
+ ) {
+ my $agentnum = $conf->config('signup_server-default_agentnum');
+ my $agent = qsearchs( 'agent', { 'agentnum' => $agentnum } )
+ or die "fatal: signup_server-default_agentnum $agentnum not found\n";
+ my $pkgpart_href = $agent->pkgpart_hashref;
+
+ $signup_info->{'part_pkg'} = [
+ #map { $_->hashref }
+ map { { 'payby' => [ $_->payby ], %{$_->hashref} } }
+ grep { $_->svcpart('svc_acct') && $pkgpart_href->{ $_->pkgpart } }
+ qsearch( 'part_pkg', { 'disabled' => '' } )
+ ];
+ }
+
+ $signup_info;
+
+}
+
+sub new_customer {
+ my $packet = shift;
+
+ my $conf = new FS::Conf;
+
+ #things that aren't necessary in base class, but are for signup server
+ #return "Passwords don't match"
+ # if $hashref->{'_password'} ne $hashref->{'_password2'}
+ return { 'error' => gettext('empty_password') }
+ unless $packet->{'_password'};
+ # a bit inefficient for large numbers of pops
+ return { 'error' => gettext('no_access_number_selected') }
+ unless $packet->{'popnum'} || !scalar(qsearch('svc_acct_pop',{} ));
+
+ #shares some stuff with htdocs/edit/process/cust_main.cgi... take any
+ # common that are still here and library them.
+ my $cust_main = new FS::cust_main ( {
+ #'custnum' => '',
+ 'agentnum' => $packet->{agentnum}
+ || $conf->config('signup_server-default_agentnum'),
+ 'refnum' => $packet->{refnum}
+ || $conf->config('signup_server-default_refnum'),
+
+ map { $_ => $packet->{$_} } qw(
+ last first ss company address1 address2 city county state zip country
+ daytime night fax payby payinfo paycvv paydate payname referral_custnum
+ comments
+ ),
+
+ } );
+
+ return { 'error' => "Illegal payment type" }
+ unless grep { $_ eq $packet->{'payby'} }
+ $conf->config('signup_server-payby');
+
+ $cust_main->payinfo($cust_main->daytime)
+ if $cust_main->payby eq 'LECB' && ! $cust_main->payinfo;
+
+ my @invoicing_list = split( /\s*\,\s*/, $packet->{'invoicing_list'} );
+
+ $packet->{'pkgpart'} =~ /^(\d+)$/ or '' =~ /^()$/;
+ my $pkgpart = $1;
+ return { 'error' => 'Please select a package' } unless $pkgpart; #msgcat
+
+ my $part_pkg =
+ qsearchs( 'part_pkg', { 'pkgpart' => $pkgpart } )
+ or return { 'error' => "WARNING: unknown pkgpart: $pkgpart" };
+ my $svcpart = $part_pkg->svcpart('svc_acct');
+
+ my $cust_pkg = new FS::cust_pkg ( {
+ #later#'custnum' => $custnum,
+ 'pkgpart' => $packet->{'pkgpart'},
+ } );
+ my $error = $cust_pkg->check;
+ return { 'error' => $error } if $error;
+
+ my $svc_acct = new FS::svc_acct ( {
+ 'svcpart' => $svcpart,
+ map { $_ => $packet->{$_} }
+ qw( username _password sec_phrase popnum ),
+ } );
+
+ my @acct_snarf;
+ my $snarfnum = 1;
+ while ( length($packet->{"snarf_machine$snarfnum"}) ) {
+ my $acct_snarf = new FS::acct_snarf ( {
+ 'machine' => $packet->{"snarf_machine$snarfnum"},
+ 'protocol' => $packet->{"snarf_protocol$snarfnum"},
+ 'username' => $packet->{"snarf_username$snarfnum"},
+ '_password' => $packet->{"snarf_password$snarfnum"},
+ } );
+ $snarfnum++;
+ push @acct_snarf, $acct_snarf;
+ }
+ $svc_acct->child_objects( \@acct_snarf );
+
+ my $y = $svc_acct->setdefault; # arguably should be in new method
+ return { 'error' => $y } if $y && !ref($y);
+
+ $error = $svc_acct->check;
+ return { 'error' => $error } if $error;
+
+ use Tie::RefHash;
+ tie my %hash, 'Tie::RefHash';
+ %hash = ( $cust_pkg => [ $svc_acct ] );
+ #msgcat
+ $error = $cust_main->insert( \%hash, \@invoicing_list, 'noexport' => 1 );
+ return { 'error' => $error } if $error;
+
+ if ( $conf->exists('signup_server-realtime') ) {
+
+ #warn "[fs_signup_server] Billing customer...\n" if $Debug;
+
+ my $bill_error = $cust_main->bill;
+ #warn "[fs_signup_server] error billing new customer: $bill_error"
+ # if $bill_error;
+
+ $cust_main->apply_payments;
+ $cust_main->apply_credits;
+
+ $bill_error = $cust_main->collect;
+ #warn "[fs_signup_server] error collecting from new customer: $bill_error"
+ # if $bill_error;
+
+ if ( $cust_main->balance > 0 ) {
+
+ #this makes sense. credit is "un-doing" the invoice
+ $cust_main->credit( $cust_main->balance, 'signup server decline' );
+ $cust_main->apply_credits;
+
+ #should check list for errors...
+ #$cust_main->suspend;
+ local $FS::svc_Common::noexport_hack = 1;
+ $cust_main->cancel('quiet'=>1);
+
+ return { 'error' => '_decline' };
+ }
+
+ }
+ $cust_main->reexport;
+
+ return { error => '' };
+
+}
+
+1;
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index d185f8d41..99eee18ea 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -174,7 +174,7 @@ sub config_items {
my $self = shift;
#quelle kludge
@config_items,
- map {
+ ( map {
my $basename = basename($_);
$basename =~ /^(.*)$/;
$basename = $1;
@@ -185,7 +185,19 @@ sub config_items {
'type' => 'textarea',
}
} glob($self->dir. '/invoice_template_*')
- ;
+ ),
+ ( map {
+ my $basename = basename($_);
+ $basename =~ /^(.*)$/;
+ $basename = $1;
+ new FS::ConfItem {
+ 'key' => $basename,
+ 'section' => 'billing',
+ 'description' => 'Alternate LaTeX template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
+ 'type' => 'textarea',
+ }
+ } glob($self->dir. '/invoice_latex_*')
+ );
}
=back
@@ -320,7 +332,14 @@ httemplate/docs/config.html
{
'key' => 'deletepayments',
'section' => 'UI',
- 'description' => 'Enable deletion of unclosed payments. Be very careful! Only delete payments that were data-entry errors, not adjustments. Optionally specify one or more comma-separated email addresses to be notified when a payment is deleted.',
+ 'description' => 'Enable deletion of unclosed payments. Be very careful! Only delete payments that were data-entry errors, not adjustments. Optionally specify one or more comma-separated email addresses to be notified when a payment is deleted.',
+ 'type' => [qw( checkbox text )],
+ },
+
+ {
+ 'key' => 'deletecredits',
+ 'section' => 'UI',
+ 'description' => '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.',
'type' => [qw( checkbox text )],
},
@@ -451,6 +470,49 @@ httemplate/docs/config.html
},
{
+ 'key' => 'invoice_latex',
+ 'section' => 'billing',
+ 'description' => 'Optional LaTeX template for typeset PostScript invoices.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'invoice_latexnotes',
+ 'section' => 'billing',
+ 'description' => 'Notes section for LaTeX typeset PostScript invoices.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'invoice_latexfooter',
+ 'section' => 'billing',
+ 'description' => 'Footer for LaTeX typeset PostScript invoices.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'invoice_latexsmallfooter',
+ 'section' => 'billing',
+ 'description' => 'Optional small footer for multi-page LaTeX typeset PostScript invoices.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'invoice_default_terms',
+ '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' ],
+ },
+
+ {
+ 'key' => 'invoice_send_receipts',
+ 'section' => 'billing',
+ 'description' => 'Send receipts for payments and credits.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'lpr',
'section' => 'required',
'description' => 'Print command for paper invoices, for example `lpr -h\'',
@@ -760,7 +822,7 @@ httemplate/docs/config.html
{
'key' => 'username-ampersand',
'section' => 'username',
- 'description' => 'Allow the ampersand character (&amp;) in usernames. Be careful when using this option in conjunction with <a href="#shellmachine-useradd">shellmachine-useradd</a> and other configuration options which execute shell commands, as the ampersand will be interpreted by the shell if not quoted.',
+ 'description' => 'Allow the ampersand character (&amp;) in usernames. Be careful when using this option in conjunction with <a href="../browse/part_export.cgi">exports</a> which execute shell commands, as the ampersand will be interpreted by the shell if not quoted.',
'type' => 'checkbox',
},
@@ -888,15 +950,15 @@ httemplate/docs/config.html
{
'key' => 'selfservice_server-quiet',
- 'section' => '',
- 'description' => 'Disable decline and cancel emails generated by transactions initiated by the selfservice server. Not recommended, unless the customer will get instant feedback from a customer service UI, and receiving an email would be confusing/overkill.',
+ 'section' => 'deprecated',
+ 'description' => '<b>DEPRECATED</b>, the self-service server no longer sends superfluous decline and cancel emails. Used to disable decline and cancel emails generated by transactions initiated by the selfservice server.',
'type' => 'checkbox',
},
{
'key' => 'signup_server-quiet',
- 'section' => '',
- 'description' => 'Disable decline and cancel emails generated by transactions initiated by the signup server. Not recommended, unless the customer will get instant feedback from a customer service UI, and receiving an email would be confusing/overkill. Does not disable welcome emails.',
+ 'section' => 'deprecated',
+ 'description' => '<b>DEPRECATED</b>, the signup server is now part of the self-service server and no longer sends superfluous decline and cancel emails. Used to disable decline and cancel emails generated by transactions initiated by the signup server. Does not disable welcome emails.',
'type' => 'checkbox',
},
@@ -910,11 +972,24 @@ httemplate/docs/config.html
{
'key' => 'signup_server-email',
+ 'section' => 'deprecated',
+ 'description' => '<b>DEPRECATED</b>, this feature is no longer available. See the ***fill me in*** report instead. Used to contain a comma-separated list of email addresses to receive notification of signups via the signup server.',
+ 'type' => 'text',
+ },
+
+ {
+ 'key' => 'signup_server-default_agentnum',
'section' => '',
- 'description' => 'Comma-separated list of email addresses to receive notification of signups via the signup server.',
+ 'description' => 'Default agentnum for the signup server',
'type' => 'text',
},
+ {
+ 'key' => 'signup_server-default_refnum',
+ 'section' => '',
+ 'description' => 'Default advertising source number for the signup server',
+ 'type' => 'text',
+ },
{
'key' => 'show-msgcat-codes',
@@ -945,6 +1020,13 @@ httemplate/docs/config.html
},
{
+ 'key' => 'emaildecline-exclude',
+ 'section' => 'billing',
+ 'description' => 'List of error messages that should not trigger email decline notices, one per line.',
+ 'type' => 'textarea',
+ },
+
+ {
'key' => 'cancelmessage',
'section' => 'billing',
'description' => 'Template file for cancellation emails.',
@@ -1053,6 +1135,42 @@ httemplate/docs/config.html
'type' => 'text',
},
+ {
+ 'key' => 'users-allow_comp',
+ 'section' => '',
+ 'description' => 'Usernames (Freeside users, created with <a href="../docs/man/bin/freeside-adduser.html">freeside-adduser</a>) which can create complimentary customers, one per line. If no usernames are entered, all users can create complimentary accounts.',
+ 'type' => 'textarea',
+ },
+
+ {
+ 'key' => 'cvv-save',
+ 'section' => 'billing',
+ 'description' => 'Save CVV2 information after the initial transaction for the selected credit card types. Enabling this option may be in violation of your merchant agreement(s), so please check them carefully before enabling this option for any credit card types.',
+ 'type' => 'selectmultiple',
+ 'select_enum' => [ "VISA card",
+ "MasterCard",
+ "Discover card",
+ "American Express card",
+ "Diner's Club/Carte Blanche",
+ "enRoute",
+ "JCB",
+ "BankCard",
+ ],
+ },
+
+ {
+ 'key' => 'allow_negative_charges',
+ 'section' => 'billing',
+ 'description' => 'Allow negative charges. Normally not used unless importing data from a legacy system that requires this.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'system_usernames',
+ 'section' => 'username',
+ 'description' => 'A list of system usernames that cannot be edited or removed, one per line. Use a bare username to prohibit modification/deletion of the username in any domain, or username@domain to prohibit modification/deletetion of a specific username and domain.',
+ 'type' => 'textarea',
+ },
);
1;
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index 9d82d949b..801b89daf 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -2,14 +2,14 @@ package FS::Record;
use strict;
use vars qw( $dbdef_file $dbdef $setup_hack $AUTOLOAD @ISA @EXPORT_OK $DEBUG
- $me %dbdef_cache );
+ $me %dbdef_cache %virtual_fields_cache );
use subs qw(reload_dbdef);
use Exporter;
use Carp qw(carp cluck croak confess);
use File::CounterFile;
use Locale::Country;
use DBI qw(:sql_types);
-use DBIx::DBSchema 0.21;
+use DBIx::DBSchema 0.23;
use FS::UID qw(dbh getotaker datasrc driver_name);
use FS::SearchCache;
use FS::Msgcat qw(gettext);
@@ -21,7 +21,7 @@ use Tie::IxHash;
@ISA = qw(Exporter);
@EXPORT_OK = qw(dbh fields hfields qsearch qsearchs dbdef jsearch);
-$DEBUG = 2;
+$DEBUG = 0;
$me = '[FS::Record]';
#ask FS::UID to run this stuff for us later
@@ -230,7 +230,8 @@ sub qsearch {
if ( ! defined( $record->{$_} ) || $record->{$_} eq '' ) {
if ( $op eq '=' ) {
if ( driver_name eq 'Pg' ) {
- if ( $dbdef->table($table)->column($column)->type =~ /(int)/i ) {
+ my $type = $dbdef->table($table)->column($column)->type;
+ if ( $type =~ /(int|serial)/i ) {
qq-( $column IS NULL )-;
} else {
qq-( $column IS NULL OR $column = '' )-;
@@ -240,7 +241,8 @@ sub qsearch {
}
} elsif ( $op eq '!=' ) {
if ( driver_name eq 'Pg' ) {
- if ( $dbdef->table($table)->column($column)->type =~ /(int)/i ) {
+ my $type = $dbdef->table($table)->column($column)->type;
+ if ( $type =~ /(int|serial)/i ) {
qq-( $column IS NOT NULL )-;
} else {
qq-( $column IS NOT NULL AND $column != '' )-;
@@ -309,7 +311,7 @@ sub qsearch {
grep defined( $record->{$_} ) && $record->{$_} ne '', @real_fields
) {
if ( $record->{$field} =~ /^\d+(\.\d+)?$/
- && $dbdef->table($table)->column($field)->type =~ /(int)/i
+ && $dbdef->table($table)->column($field)->type =~ /(int|serial)/i
) {
$sth->bind_param($bind++, $record->{$field}, { TYPE => SQL_INTEGER } );
} else {
@@ -664,7 +666,7 @@ sub insert {
if (@virtual_fields) {
my %v_values = map { $_, $self->getfield($_) } @virtual_fields;
- my $vfieldpart = vfieldpart_hashref($table);
+ my $vfieldpart = $self->vfieldpart_hashref;
my $v_statement = "INSERT INTO virtual_field(recnum, vfieldpart, value) ".
"VALUES (?, ?, ?)";
@@ -753,7 +755,7 @@ sub delete {
my $primary_key = $self->dbdef_table->primary_key;
my $v_sth;
my @del_vfields;
- my $vfp = vfieldpart_hashref($self->table);
+ my $vfp = $self->vfieldpart_hashref;
foreach($self->virtual_fields) {
next if $self->getfield($_) eq '';
unless(@del_vfields) {
@@ -804,7 +806,24 @@ returns the error, otherwise returns false.
=cut
sub replace {
- my ( $new, $old ) = ( shift, shift );
+ my $new = shift;
+
+ my $old;
+ if ( @_ ) {
+ $old = shift;
+ } else {
+ warn "[debug]$me replace called with no arguments; autoloading old record\n"
+ if $DEBUG;
+ my $primary_key = $new->dbdef_table->primary_key;
+ if ( $primary_key ) {
+ $old = qsearchs($new->table, { $primary_key => $new->$primary_key() } )
+ or croak "can't find ". $new->table. ".$primary_key ".
+ $new->$primary_key();
+ } else {
+ croak $new->table. " has no primary key; pass old record as argument";
+ }
+ }
+
warn "[debug]$me $new ->replace $old\n" if $DEBUG;
return "Records not in same table!" unless $new->table eq $old->table;
@@ -836,7 +855,7 @@ sub replace {
$old->getfield($_) eq ''
#? "( $_ IS NULL OR $_ = \"\" )"
? ( driver_name eq 'Pg'
- ? "$_ IS NULL"
+ ? "( $_ IS NULL OR $_ = '' )"
: "( $_ IS NULL OR $_ = \"\" )"
)
: "$_ = ". _quote($old->getfield($_),$old->table,$_)
@@ -870,7 +889,7 @@ sub replace {
my $v_rep_sth;
my $v_del_sth;
my (@add_vfields, @rep_vfields, @del_vfields);
- my $vfp = vfieldpart_hashref($old->table);
+ my $vfp = $old->vfieldpart_hashref;
foreach(grep { exists($diff{$_}) } $new->virtual_fields) {
if($diff{$_} eq '') {
# Delete
@@ -1051,6 +1070,21 @@ sub ut_float {
'';
}
+=item ut_snumber COLUMN
+
+Check/untaint signed numeric data (whole numbers). May not be null. If there
+is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub ut_snumber {
+ my($self, $field) = @_;
+ $self->getfield($field) =~ /^(-?)\s*(\d+)$/
+ or return "Illegal or empty (numeric) $field: ". $self->getfield($field);
+ $self->setfield($field, "$1$2");
+ '';
+}
+
=item ut_number COLUMN
Check/untaint simple numeric data (whole numbers). May not be null. If there
@@ -1369,20 +1403,25 @@ be exported, and should only be called as an instance or class method.
=cut
sub virtual_fields {
- my $something = shift;
+ my $self = shift;
my $table;
- $table = $something->table or confess "virtual_fields called on non-table";
+ $table = $self->table or confess "virtual_fields called on non-table";
confess "Unknown table $table" unless $dbdef->table($table);
- # This should be smart enough to cache results.
+ return () unless $self->dbdef->table('part_virtual_field');
+
+ unless ( $virtual_fields_cache{$table} ) {
+ my $query = 'SELECT name from part_virtual_field ' .
+ "WHERE dbtable = '$table'";
+ my $dbh = dbh;
+ my $result = $dbh->selectcol_arrayref($query);
+ confess $dbh->errstr if $dbh->err;
+ $virtual_fields_cache{$table} = $result;
+ }
+
+ @{$virtual_fields_cache{$table}};
- my $query = 'SELECT name from part_virtual_field ' .
- "WHERE dbtable = '$table'";
- my $dbh = dbh;
- my $result = $dbh->selectcol_arrayref($query);
- confess $dbh->errstr if $dbh->err;
- return @$result;
}
@@ -1509,9 +1548,11 @@ TABLE.
=cut
sub vfieldpart_hashref {
- my ($table) = @_;
+ my $self = shift;
+ my $table = $self->table;
+
+ return {} unless $self->dbdef->table('part_virtual_field');
- return () unless $table;
my $dbh = dbh;
my $statement = "SELECT vfieldpart, name FROM part_virtual_field WHERE ".
"dbtable = '$table'";
diff --git a/FS/FS/UID.pm b/FS/FS/UID.pm
index f67005151..8271f89f2 100644
--- a/FS/FS/UID.pm
+++ b/FS/FS/UID.pm
@@ -87,7 +87,7 @@ sub forksuidsetup {
getsecrets;
$dbh = DBI->connect($datasrc,$db_user,$db_pass, {
'AutoCommit' => 0,
- #'ChopBlanks' => 1,
+ 'ChopBlanks' => 1,
} ) or die "DBI->connect error: $DBI::errstr\n";
foreach ( keys %callback ) {
diff --git a/FS/FS/acct_snarf.pm b/FS/FS/acct_snarf.pm
new file mode 100644
index 000000000..b4e88bfc9
--- /dev/null
+++ b/FS/FS/acct_snarf.pm
@@ -0,0 +1,128 @@
+package FS::acct_snarf;
+
+use strict;
+use vars qw( @ISA );
+use FS::Record;
+
+@ISA = qw( FS::Record );
+
+=head1 NAME
+
+FS::acct_snarf - Object methods for acct_snarf records
+
+=head1 SYNOPSIS
+
+ use FS::acct_snarf;
+
+ $record = new FS::acct_snarf \%hash;
+ $record = new FS::acct_snarf { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::svc_acct object represents an external mail account, typically for
+download of mail. FS::acct_snarf inherits from FS::Record. The following
+fields are currently supported:
+
+=over 4
+
+=item snarfnum - primary key
+
+=item svcnum - Account (see L<FS::svc_acct>)
+
+=item machine - external machine to download mail from
+
+=item protocol - protocol (pop3, imap, etc.)
+
+=item username - external login username
+
+=item _password - external login password
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'acct_snarf'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+# the insert method can be inherited from FS::Record
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+# the delete method can be inherited from FS::Record
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+# the replace method can be inherited from FS::Record
+
+=item check
+
+Checks all fields to make sure this is a valid external mail account. If
+there is an error, returns the error, otherwise returns false. Called by the
+insert and replace methods.
+
+=cut
+
+sub check {
+ my $self = shift;
+ my $error =
+ $self->ut_numbern('snarfnum')
+ || $self->ut_number('svcnum')
+ || $self->ut_foreign_key('svcnum', 'svc_acct', 'svcnum')
+ || $self->ut_domain('machine')
+ || $self->ut_alphan('protocol')
+ || $self->ut_textn('username')
+ ;
+ return $error if $error;
+
+ $self->_password =~ /^[^\t\n]*$/ or return "illegal password";
+ $self->_password($1);
+
+ ''; #no error
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm
index 4b034ef0c..1fb60606d 100755
--- a/FS/FS/addr_block.pm
+++ b/FS/FS/addr_block.pm
@@ -176,11 +176,12 @@ sub next_free_addr {
my $conf = new FS::Conf;
my @excludeaddr = $conf->config('exclude_ip_addr');
- my @used = (
- map { $_->NetAddr->addr }
- ($self,
- qsearch('svc_broadband', { blocknum => $self->blocknum }) ),
- @excludeaddr );
+my @used =
+( (map { $_->NetAddr->addr }
+ ($self,
+ qsearch('svc_broadband', { blocknum => $self->blocknum }))
+ ), @excludeaddr
+);
my @free = $self->NetAddr->hostenum;
while (my $ip = shift @free) {
diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm
index 6de15ae6f..2f70d654d 100644
--- a/FS/FS/agent.pm
+++ b/FS/FS/agent.pm
@@ -50,6 +50,12 @@ from FS::Record. The following fields are currently supported:
=item freq - For future use.
+=item disabled - Disabled flag, empty or 'Y'
+
+=item username - Username for the Agent interface
+
+=item _password - Password for the Agent interface
+
=back
=head1 METHODS
@@ -110,6 +116,24 @@ sub check {
;
return $error if $error;
+ if ( $self->dbdef_table->column('disabled') ) {
+ $error = $self->ut_enum('disabled', [ '', 'Y' ] );
+ return $error if $error;
+ }
+
+ if ( $self->dbdef_table->column('username') ) {
+ $error = $self->ut_alphan('username');
+ return $error if $error;
+ if ( length($self->username) ) {
+ my $conflict = qsearchs('agent', { 'username' => $self->username } );
+ return 'duplicate agent username (with '. $conflict->agent. ')'
+ if $conflict;
+ $error = $self->ut_text('password'); # ut_text... arbitrary choice
+ } else {
+ $self->_password('');
+ }
+ }
+
return "Unknown typenum!"
unless $self->agent_type;
@@ -144,7 +168,7 @@ sub pkgpart_hashref {
=head1 VERSION
-$Id: agent.pm,v 1.4 2003-08-05 00:20:40 khoff Exp $
+$Id: agent.pm,v 1.6 2003-09-30 15:01:46 ivan Exp $
=head1 BUGS
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index 4793608c0..a3e76620e 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -343,6 +343,10 @@ sub send {
}
+ if ( $conf->config('invoice_latex') ) {
+ @print_text = $self->print_ps('', $template);
+ }
+
if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal
my $lpr = $conf->config('lpr');
open(LPR, "|$lpr")
@@ -590,7 +594,10 @@ sub realtime_bop {
my( $self, $method ) = @_;
my $cust_main = $self->cust_main;
- my $amount = $self->owed;
+ my $balance = $cust_main->balance;
+ my $amount = ( $balance < $self->owed ) ? $balance : $self->owed;
+ $amount = sprintf("%.2f", $amount);
+ return "not run (balance $balance)" unless $amount > 0;
my $description = 'Internet Services';
if ( $conf->exists('business-onlinepayment-description') ) {
@@ -636,7 +643,6 @@ sub batch_card {
'state' => $cust_main->getfield('state'),
'zip' => $cust_main->getfield('zip'),
'country' => $cust_main->getfield('country'),
- 'trancode' => 77,
'cardnum' => $cust_main->getfield('payinfo'),
'exp' => $cust_main->getfield('paydate'),
'payname' => $cust_main->getfield('payname'),
@@ -648,7 +654,7 @@ sub batch_card {
'';
}
-=item print_text [TIME];
+=item print_text [ TIME [ , TEMPLATE ] ]
Returns an text invoice, as a list of lines.
@@ -705,7 +711,9 @@ sub print_text {
my $pkg = $part_pkg->pkg;
if ( $cust_bill_pkg->setup != 0 ) {
- push @buf, [ "$pkg Setup",
+ my $description = $pkg;
+ $description .= ' Setup' if $cust_bill_pkg->recur != 0;
+ push @buf, [ $description,
$money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ];
push @buf,
map { [ " ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels;
@@ -783,8 +791,10 @@ sub print_text {
}
#balance due
+ my $balance_due_msg = $self->balance_due_msg;
+
push @buf,['','-----------'];
- push @buf,['Balance Due', $money_char.
+ push @buf,[$balance_due_msg, $money_char.
sprintf("%10.2f", $balance_due ) ];
#create the template
@@ -878,6 +888,505 @@ sub print_text {
}
+=item print_latex [ TIME [ , TEMPLATE ] ]
+
+Internal method - returns a filename of a filled-in LaTeX template for this
+invoice (Note: add ".tex" to get the actual filename).
+
+See print_ps and print_pdf for methods that return PostScript and PDF output.
+
+TIME an optional value used to control the printing of overdue messages. The
+default is now. It isn't the date of the invoice; that's the `_date' field.
+It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=cut
+
+#still some false laziness w/print_text
+sub print_latex {
+
+ my( $self, $today, $template ) = @_;
+ $today ||= time;
+
+# my $invnum = $self->invnum;
+ my $cust_main = $self->cust_main;
+ $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') )
+ unless $cust_main->payname && $cust_main->payby ne 'CHEK';
+
+ my( $pr_total, @pr_cust_bill ) = $self->previous; #previous balance
+# my( $cr_total, @cr_cust_credit ) = $self->cust_credit; #credits
+ #my $balance_due = $self->owed + $pr_total - $cr_total;
+ my $balance_due = $self->owed + $pr_total;
+
+ #my @collect = ();
+ #my($description,$amount);
+ @buf = ();
+
+ #create the template
+ my $templatefile = 'invoice_latex';
+ $templatefile .= "_$template" if $template;
+ my @invoice_template = $conf->config($templatefile)
+ or die "cannot load config file $templatefile";
+
+ my %invoice_data = (
+ 'invnum' => $self->invnum,
+ 'date' => time2str('%b %o, %Y', $self->_date),
+ 'agent' => _latex_escape($cust_main->agent->agent),
+ 'payname' => _latex_escape($cust_main->payname),
+ 'company' => _latex_escape($cust_main->company),
+ 'address1' => _latex_escape($cust_main->address1),
+ 'address2' => _latex_escape($cust_main->address2),
+ 'city' => _latex_escape($cust_main->city),
+ 'state' => _latex_escape($cust_main->state),
+ 'zip' => _latex_escape($cust_main->zip),
+ 'country' => _latex_escape($cust_main->country),
+ 'footer' => join("\n", $conf->config('invoice_latexfooter') ),
+ 'smallfooter' => join("\n", $conf->config('invoice_latexsmallfooter') ),
+ 'quantity' => 1,
+ 'terms' => $conf->config('invoice_default_terms') || 'Payable upon receipt',
+ #'notes' => join("\n", $conf->config('invoice_latexnotes') ),
+ );
+
+ my $countrydefault = $conf->config('countrydefault') || 'US';
+ $invoice_data{'country'} = '' if $invoice_data{'country'} eq $countrydefault;
+
+ #do variable substitutions in notes
+ $invoice_data{'notes'} =
+ join("\n",
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ $conf->config('invoice_latexnotes')
+ );
+
+ $invoice_data{'footer'} =~ s/\n+$//;
+ $invoice_data{'smallfooter'} =~ s/\n+$//;
+ $invoice_data{'notes'} =~ s/\n+$//;
+
+ $invoice_data{'po_line'} =
+ ( $cust_main->payby eq 'BILL' && $cust_main->payinfo )
+ ? _latex_escape("Purchase Order #". $cust_main->payinfo)
+ : '~';
+
+ my @line_item = ();
+ my @total_item = ();
+ my @filled_in = ();
+ while ( @invoice_template ) {
+ my $line = shift @invoice_template;
+
+ if ( $line =~ /^%%Detail\s*$/ ) {
+
+ while ( ( my $line_item_line = shift @invoice_template )
+ !~ /^%%EndDetail\s*$/ ) {
+ push @line_item, $line_item_line;
+ }
+ foreach my $line_item ( $self->_items ) {
+ #foreach my $line_item ( $self->_items_pkg ) {
+ $invoice_data{'ref'} = $line_item->{'pkgnum'};
+ $invoice_data{'description'} = _latex_escape($line_item->{'description'});
+ if ( exists $line_item->{'ext_description'} ) {
+ $invoice_data{'description'} .=
+ "\\tabularnewline\n~~".
+ join("\\tabularnewline\n~~", map { _latex_escape($_) } @{$line_item->{'ext_description'}} );
+ }
+ $invoice_data{'amount'} = $line_item->{'amount'};
+ $invoice_data{'product_code'} = $line_item->{'pkgpart'} || 'N/A';
+ push @filled_in,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b } @line_item;
+ }
+
+ } elsif ( $line =~ /^%%TotalDetails\s*$/ ) {
+
+ while ( ( my $total_item_line = shift @invoice_template )
+ !~ /^%%EndTotalDetails\s*$/ ) {
+ push @total_item, $total_item_line;
+ }
+
+ my @total_fill = ();
+
+ my $taxtotal = 0;
+ foreach my $tax ( $self->_items_tax ) {
+ $invoice_data{'total_item'} = _latex_escape($tax->{'description'});
+ $taxtotal += ( $invoice_data{'total_amount'} = $tax->{'amount'} );
+ push @total_fill,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ @total_item;
+ }
+
+ if ( $taxtotal ) {
+ $invoice_data{'total_item'} = 'Sub-total';
+ $invoice_data{'total_amount'} =
+ '\dollar '. sprintf('%.2f', $self->charged - $taxtotal );
+ unshift @total_fill,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ @total_item;
+ }
+
+ $invoice_data{'total_item'} = '\textbf{Total}';
+ $invoice_data{'total_amount'} =
+ '\textbf{\dollar '. sprintf('%.2f', $self->charged + $pr_total ). '}';
+ push @total_fill,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ @total_item;
+
+ #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments
+
+ # credits
+ foreach my $credit ( $self->_items_credits ) {
+ $invoice_data{'total_item'} = _latex_escape($credit->{'description'});
+ #$credittotal
+ $invoice_data{'total_amount'} = '-\dollar '. $credit->{'amount'};
+ push @total_fill,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ @total_item;
+ }
+
+ # payments
+ foreach my $payment ( $self->_items_payments ) {
+ $invoice_data{'total_item'} = _latex_escape($payment->{'description'});
+ #$paymenttotal
+ $invoice_data{'total_amount'} = '-\dollar '. $payment->{'amount'};
+ push @total_fill,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ @total_item;
+ }
+
+ $invoice_data{'total_item'} = '\textbf{'. $self->balance_due_msg. '}';
+ $invoice_data{'total_amount'} =
+ '\textbf{\dollar '. sprintf('%.2f', $self->owed + $pr_total ). '}';
+ push @total_fill,
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ @total_item;
+
+ push @filled_in, @total_fill;
+
+ } else {
+ #$line =~ s/\$(\w+)/$invoice_data{$1}/eg;
+ $line =~ s/\$(\w+)/exists($invoice_data{$1}) ? $invoice_data{$1} : nounder($1)/eg;
+ push @filled_in, $line;
+ }
+
+ }
+
+ sub nounder {
+ my $var = $1;
+ $var =~ s/_/\-/g;
+ $var;
+ }
+
+ my $dir = '/tmp'; #! /usr/local/etc/freeside/invoices.datasrc/
+ my $unique = int(rand(2**31)); #UGH... use File::Temp or something
+
+ chdir($dir);
+ my $file = $self->invnum. ".$unique";
+
+ open(TEX,">$file.tex") or die "can't open $file.tex: $!\n";
+ print TEX join("\n", @filled_in ), "\n";
+ close TEX;
+
+ return $file;
+
+}
+
+=item print_ps [ TIME [ , TEMPLATE ] ]
+
+Returns an postscript invoice, as a scalar.
+
+TIME an optional value used to control the printing of overdue messages. The
+default is now. It isn't the date of the invoice; that's the `_date' field.
+It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=cut
+
+sub print_ps {
+ my $self = shift;
+
+ my $file = $self->print_latex(@_);
+
+ #error checking!!
+ system('pslatex', "$file.tex");
+ system('pslatex', "$file.tex");
+ system('dvips', '-q', '-t', 'letter', "$file.dvi", '-o', "$file.ps" );
+
+ open(POSTSCRIPT, "<$file.ps")
+ or die "can't open $file.ps (probable error in LaTeX template): $!\n";
+
+ unlink("$file.dvi", "$file.log", "$file.aux", "$file.ps", "$file.tex");
+
+ my $ps = '';
+ while (<POSTSCRIPT>) {
+ $ps .= $_;
+ }
+
+ close POSTSCRIPT;
+
+ return $ps;
+
+}
+
+=item print_pdf [ TIME [ , TEMPLATE ] ]
+
+Returns an PDF invoice, as a scalar.
+
+TIME an optional value used to control the printing of overdue messages. The
+default is now. It isn't the date of the invoice; that's the `_date' field.
+It is specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=cut
+
+sub print_pdf {
+ my $self = shift;
+
+ my $file = $self->print_latex(@_);
+
+ #system('pdflatex', "$file.tex");
+ #system('pdflatex', "$file.tex");
+ #! LaTeX Error: Unknown graphics extension: .eps.
+
+ #error checking!!
+ system('pslatex', "$file.tex");
+ system('pslatex', "$file.tex");
+
+ #system('dvipdf', "$file.dvi", "$file.pdf" );
+ system("dvips -q -t letter -f $file.dvi | gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$file.pdf -c save pop -");
+
+ open(PDF, "<$file.pdf")
+ or die "can't open $file.pdf (probably error in LaTeX tempalte: $!\n";
+
+ unlink("$file.dvi", "$file.log", "$file.aux", "$file.pdf", "$file.tex");
+
+ my $pdf = '';
+ while (<PDF>) {
+ $pdf .= $_;
+ }
+
+ close PDF;
+
+ return $pdf;
+
+}
+
+# quick subroutine for print_latex
+#
+# There are ten characters that LaTeX treats as special characters, which
+# means that they do not simply typeset themselves:
+# # $ % & ~ _ ^ \ { }
+#
+# TeX ignores blanks following an escaped character; if you want a blank (as
+# in "10% of ..."), you have to "escape" the blank as well ("10\%\ of ...").
+
+sub _latex_escape {
+ my $value = shift;
+ $value =~ s/([#\$%&~_\^{}])( )?/"\\$1". ( length($2) ? "\\$2" : '' )/ge;
+ $value;
+}
+
+#utility methods for print_*
+
+sub balance_due_msg {
+ my $self = shift;
+ my $msg = 'Balance Due';
+ return $msg unless $conf->exists('invoice_default_terms');
+ if ( $conf->config('invoice_default_terms') =~ /^\s*Net\s*(\d+)\s*$/ ) {
+ $msg .= ' - Please pay by '. time2str("%x", $self->_date + ($1*86400) );
+ } elsif ( $conf->config('invoice_default_terms') ) {
+ $msg .= ' - '. $conf->config('invoice_default_terms');
+ }
+ $msg;
+}
+
+sub _items {
+ my $self = shift;
+ my @display = scalar(@_)
+ ? @_
+ : qw( _items_previous _items_pkg );
+ #: qw( _items_pkg );
+ #: qw( _items_previous _items_pkg _items_tax _items_credits _items_payments );
+ my @b = ();
+ foreach my $display ( @display ) {
+ push @b, $self->$display(@_);
+ }
+ @b;
+}
+
+sub _items_previous {
+ my $self = shift;
+ my $cust_main = $self->cust_main;
+ my( $pr_total, @pr_cust_bill ) = $self->previous; #previous balance
+ my @b = ();
+ foreach ( @pr_cust_bill ) {
+ push @b, {
+ 'description' => 'Previous Balance, Invoice #'. $_->invnum.
+ ' ('. time2str('%x',$_->_date). ')',
+ #'pkgpart' => 'N/A',
+ 'pkgnum' => 'N/A',
+ 'amount' => sprintf("%10.2f", $_->owed),
+ };
+ }
+ @b;
+
+ #{
+ # 'description' => 'Previous Balance',
+ # #'pkgpart' => 'N/A',
+ # 'pkgnum' => 'N/A',
+ # 'amount' => sprintf("%10.2f", $pr_total ),
+ # 'ext_description' => [ map {
+ # "Invoice ". $_->invnum.
+ # " (". time2str("%x",$_->_date). ") ".
+ # sprintf("%10.2f", $_->owed)
+ # } @pr_cust_bill ],
+
+ #};
+}
+
+sub _items_pkg {
+ my $self = shift;
+ my @cust_bill_pkg = grep { $_->pkgnum } $self->cust_bill_pkg;
+ $self->_items_cust_bill_pkg(\@cust_bill_pkg, @_);
+}
+
+sub _items_tax {
+ my $self = shift;
+ my @cust_bill_pkg = grep { ! $_->pkgnum } $self->cust_bill_pkg;
+ $self->_items_cust_bill_pkg(\@cust_bill_pkg, @_);
+}
+
+sub _items_cust_bill_pkg {
+ my $self = shift;
+ my $cust_bill_pkg = shift;
+
+ my @b = ();
+ foreach my $cust_bill_pkg ( @$cust_bill_pkg ) {
+
+ if ( $cust_bill_pkg->pkgnum ) {
+
+ my $cust_pkg = qsearchs('cust_pkg', { pkgnum =>$cust_bill_pkg->pkgnum } );
+ my $part_pkg = qsearchs('part_pkg', { pkgpart=>$cust_pkg->pkgpart } );
+ my $pkg = $part_pkg->pkg;
+
+ my %labels;
+ #tie %labels, 'Tie::IxHash';
+ push @{ $labels{$_->[0]} }, $_->[1] foreach $cust_pkg->labels;
+ my @ext_description;
+ foreach my $label ( keys %labels ) {
+ my @values = @{ $labels{$label} };
+ my $num = scalar(@values);
+ if ( $num > 5 ) {
+ push @ext_description, "$label ($num)";
+ } else {
+ push @ext_description, map { "$label: $_" } @values;
+ }
+ }
+
+ if ( $cust_bill_pkg->setup != 0 ) {
+ my $description = $pkg;
+ $description .= ' Setup' if $cust_bill_pkg->recur != 0;
+ my @d = @ext_description;
+ push @d, $cust_bill_pkg->details if $cust_bill_pkg->recur == 0;
+ push @b, {
+ 'description' => $description,
+ #'pkgpart' => $part_pkg->pkgpart,
+ 'pkgnum' => $cust_pkg->pkgnum,
+ 'amount' => sprintf("%10.2f", $cust_bill_pkg->setup),
+ 'ext_description' => \@d,
+ };
+ }
+
+ if ( $cust_bill_pkg->recur != 0 ) {
+ push @b, {
+ 'description' => "$pkg (" .
+ time2str('%x', $cust_bill_pkg->sdate). ' - '.
+ time2str('%x', $cust_bill_pkg->edate). ')',
+ #'pkgpart' => $part_pkg->pkgpart,
+ 'pkgnum' => $cust_pkg->pkgnum,
+ 'amount' => sprintf("%10.2f", $cust_bill_pkg->recur),
+ 'ext_description' => [ @ext_description,
+ $cust_bill_pkg->details,
+ ],
+ };
+ }
+
+ } else { #pkgnum tax or one-shot line item (??)
+
+ my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc')
+ ? ( $cust_bill_pkg->itemdesc || 'Tax' )
+ : 'Tax';
+ if ( $cust_bill_pkg->setup != 0 ) {
+ push @b, {
+ 'description' => $itemdesc,
+ 'amount' => sprintf("%10.2f", $cust_bill_pkg->setup),
+ };
+ }
+ if ( $cust_bill_pkg->recur != 0 ) {
+ push @b, {
+ 'description' => "$itemdesc (".
+ time2str("%x", $cust_bill_pkg->sdate). ' - '.
+ time2str("%x", $cust_bill_pkg->edate). ')',
+ 'amount' => sprintf("%10.2f", $cust_bill_pkg->recur),
+ };
+ }
+
+ }
+
+ }
+
+ @b;
+
+}
+
+sub _items_credits {
+ my $self = shift;
+
+ my @b;
+ #credits
+ foreach ( $self->cust_credited ) {
+
+ #something more elaborate if $_->amount ne $_->cust_credit->credited ?
+
+ my $reason = $_->cust_credit->reason;
+ #my $reason = substr($_->cust_credit->reason,0,32);
+ #$reason .= '...' if length($reason) < length($_->cust_credit->reason);
+ $reason = " ($reason) " if $reason;
+ push @b, {
+ #'description' => 'Credit ref\#'. $_->crednum.
+ # " (". time2str("%x",$_->cust_credit->_date) .")".
+ # $reason,
+ 'description' => 'Credit applied'.
+ time2str("%x",$_->cust_credit->_date). $reason,
+ 'amount' => sprintf("%10.2f",$_->amount),
+ };
+ }
+ #foreach ( @cr_cust_credit ) {
+ # push @buf,[
+ # "Credit #". $_->crednum. " (" . time2str("%x",$_->_date) .")",
+ # $money_char. sprintf("%10.2f",$_->credited)
+ # ];
+ #}
+
+ @b;
+
+}
+
+sub _items_payments {
+ my $self = shift;
+
+ my @b;
+ #get & print payments
+ foreach ( $self->cust_bill_pay ) {
+
+ #something more elaborate if $_->amount ne ->cust_pay->paid ?
+
+ push @b, {
+ 'description' => "Payment received ".
+ time2str("%x",$_->cust_pay->_date ),
+ 'amount' => sprintf("%10.2f", $_->amount )
+ };
+ }
+
+ @b;
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/cust_bill_pay.pm b/FS/FS/cust_bill_pay.pm
index 5f4a49144..c8b5525ea 100644
--- a/FS/FS/cust_bill_pay.pm
+++ b/FS/FS/cust_bill_pay.pm
@@ -1,13 +1,18 @@
package FS::cust_bill_pay;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $conf );
use FS::Record qw( qsearch qsearchs dbh );
use FS::cust_bill;
use FS::cust_pay;
@ISA = qw( FS::Record );
+#ask FS::UID to run this stuff for us later
+FS::UID->install_callback( sub {
+ $conf = new FS::Conf;
+} );
+
=head1 NAME
FS::cust_bill_pay - Object methods for cust_bill_pay records
@@ -101,7 +106,8 @@ sub insert {
" greater than cust_pay.paid ". $cust_pay->paid;
}
- my $cust_bill = qsearchs('cust_bill', { 'invnum' => $self->invnum } ) or do {
+ my $cust_bill = $self->cust_bill;
+ unless ( $cust_bill ) {
$dbh->rollback if $oldAutoCommit;
return "unknown cust_bill.invnum: ". $self->invnum;
};
@@ -120,6 +126,11 @@ sub insert {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ if ( $conf->exists('invoice_send_receipts') ) {
+ my $send_error = $cust_bill->send;
+ warn "Error sending receipt: $send_error\n" if $send_error;
+ }
+
'';
}
@@ -197,10 +208,6 @@ sub cust_bill {
=back
-=head1 VERSION
-
-$Id: cust_bill_pay.pm,v 1.13 2003-08-05 00:20:41 khoff Exp $
-
=head1 BUGS
Delete and replace methods.
diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm
index e668abd73..19a54534f 100644
--- a/FS/FS/cust_credit.pm
+++ b/FS/FS/cust_credit.pm
@@ -2,8 +2,10 @@ package FS::cust_credit;
use strict;
use vars qw( @ISA $conf $unsuspendauto );
+use Date::Format;
use FS::UID qw( dbh getotaker );
use FS::Record qw( qsearch qsearchs );
+use FS::Misc qw(send_email);
use FS::cust_main;
use FS::cust_refund;
use FS::cust_credit_bill;
@@ -130,7 +132,64 @@ Currently unimplemented.
sub delete {
my $self = shift;
return "Can't delete closed credit" if $self->closed =~ /^Y/i;
- $self->SUPER::delete(@_);
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $cust_credit_bill ( $self->cust_credit_bill ) {
+ my $error = $cust_credit_bill->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ my $error = $self->SUPER::delete(@_);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ if ( $conf->config('deletecredits') ne '' ) {
+
+ my $cust_main = qsearchs('cust_main',{ 'custnum' => $self->custnum });
+
+ my $error = send_email(
+ 'from' => $conf->config('invoice_from'), #??? well as good as any
+ 'to' => $conf->config('deletecredits'),
+ 'subject' => 'FREESIDE NOTIFICATION: Credit deleted',
+ 'body' => [
+ "This is an automatic message from your Freeside installation\n",
+ "informing you that the following credit has been deleted:\n",
+ "\n",
+ 'crednum: '. $self->crednum. "\n",
+ 'custnum: '. $self->custnum.
+ " (". $cust_main->last. ", ". $cust_main->first. ")\n",
+ 'amount: $'. sprintf("%.2f", $self->amount). "\n",
+ 'date: '. time2str("%a %b %e %T %Y", $self->_date). "\n",
+ 'reason: '. $self->reason. "\n",
+ ],
+ );
+
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't send credit deletion notification: $error";
+ }
+
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
}
=item replace OLD_RECORD
@@ -141,7 +200,10 @@ posted.
=cut
sub replace {
- return "Can't modify credit!"
+ #return "Can't modify credit!"
+ my $self = shift;
+ return "Can't modify closed credit" if $self->closed =~ /^Y/i;
+ $self->SUPER::replace(@_);
}
=item check
@@ -240,13 +302,9 @@ sub credited {
=back
-=head1 VERSION
-
-$Id: cust_credit.pm,v 1.17 2003-08-05 00:20:41 khoff Exp $
-
=head1 BUGS
-The delete method.
+The delete method. The replace method.
=head1 SEE ALSO
diff --git a/FS/FS/cust_credit_bill.pm b/FS/FS/cust_credit_bill.pm
index a54acb683..bd76c2e1a 100644
--- a/FS/FS/cust_credit_bill.pm
+++ b/FS/FS/cust_credit_bill.pm
@@ -1,7 +1,7 @@
package FS::cust_credit_bill;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $conf );
use FS::UID qw( getotaker );
use FS::Record qw( qsearch qsearchs );
use FS::cust_main;
@@ -11,6 +11,11 @@ use FS::cust_bill;
@ISA = qw( FS::Record );
+#ask FS::UID to run this stuff for us later
+FS::UID->install_callback( sub {
+ $conf = new FS::Conf;
+} );
+
=head1 NAME
FS::cust_credit_bill - Object methods for cust_credit_bill records
@@ -69,6 +74,21 @@ sub table { 'cust_credit_bill'; }
Adds this cust_credit_bill to the database ("Posts" all or part of a credit).
If there is an error, returns the error, otherwise returns false.
+=cut
+
+sub insert {
+ my $self = shift;
+ my $error = $self->SUPER::insert(@_);
+ return $error if $error;
+
+ if ( $conf->exists('invoice_send_receipts') ) {
+ my $send_error = $self->cust_bill->send;
+ warn "Error sending receipt: $send_error\n" if $send_error;
+ }
+
+ '';
+}
+
=item delete
Currently unimplemented.
@@ -76,7 +96,10 @@ Currently unimplemented.
=cut
sub delete {
- return "Can't unapply credit!"
+ my $self = shift;
+ return "Can't delete application for closed credit"
+ if $self->cust_credit->closed =~ /^Y/i;
+ $self->SUPER::delete(@_);
}
=item replace OLD_RECORD
@@ -141,11 +164,18 @@ sub cust_credit {
qsearchs( 'cust_credit', { 'crednum' => $self->crednum } );
}
-=back
+=item cust_bill
+
+Returns the invoice (see L<FS::cust_bill>)
+
+=cut
-=head1 VERSION
+sub cust_bill {
+ my $self = shift;
+ qsearchs( 'cust_bill', { 'invnum' => $self->invnum } );
+}
-$Id: cust_credit_bill.pm,v 1.8 2003-08-05 00:20:41 khoff Exp $
+=back
=head1 BUGS
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 2af2e98ce..6ca32871d 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -2,11 +2,12 @@ package FS::cust_main;
use strict;
use vars qw( @ISA $conf $Debug $import );
+use vars qw( $realtime_bop_decline_quiet ); #ugh
use Safe;
use Carp;
BEGIN {
eval "use Time::Local;";
- die "Time::Local version 1.05 required with Perl versions before 5.6"
+ die "Time::Local minimum version 1.05 required with Perl versions before 5.6"
if $] < 5.006 && !defined($Time::Local::VERSION);
eval "use Time::Local qw(timelocal timelocal_nocheck);";
}
@@ -21,6 +22,7 @@ use FS::cust_bill;
use FS::cust_bill_pkg;
use FS::cust_pay;
use FS::cust_credit;
+use FS::cust_refund;
use FS::part_referral;
use FS::cust_main_county;
use FS::agent;
@@ -38,7 +40,9 @@ use FS::Msgcat qw(gettext);
@ISA = qw( FS::Record );
-$Debug = 1;
+$realtime_bop_decline_quiet = 0;
+
+$Debug = 0;
#$Debug = 1;
$import = 0;
@@ -169,6 +173,8 @@ FS::Record. The following fields are currently supported:
=item payinfo - card number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L<FS::prepay_credit>)
+=item paycvv - Card Verification Value, "CVV2" (also known as CVC2 or CID), the 3 or 4 digit number on the back (or front, for American Express) of the credit card
+
=item paydate - expiration date, mm/yyyy, m/yyyy, mm/yy or m/yy
=item payname - name on card or billing name
@@ -198,7 +204,7 @@ points to. You can ask the object for a copy with the I<hash> method.
sub table { 'cust_main'; }
-=item insert [ CUST_PKG_HASHREF [ , INVOICING_LIST_ARYREF ] ]
+=item insert [ CUST_PKG_HASHREF [ , INVOICING_LIST_ARYREF ] [ , OPTION => VALUE ... ] ]
Adds this customer to the database. If there is an error, returns the error,
otherwise returns false.
@@ -226,12 +232,18 @@ invoicing_list destination to the newly-created svc_acct. Here's an example:
$cust_main->insert( {}, [ $email, 'POST' ] );
+Currently available options are: I<noexport>
+
+If I<noexport> is set true, no provisioning jobs (exports) are scheduled.
+(You can schedule them later with the B<reexport> method.)
+
=cut
sub insert {
my $self = shift;
my $cust_pkgs = @_ ? shift : {};
my $invoicing_list = @_ ? shift : '';
+ my %options = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -283,7 +295,8 @@ sub insert {
}
# packages
- $error = $self->order_pkgs($cust_pkgs, \$seconds);
+ #local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'};
+ $error = $self->order_pkgs($cust_pkgs, \$seconds, %options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -317,9 +330,27 @@ sub insert {
}
-=item order_pkgs
+=item order_pkgs HASHREF, [ , OPTION => VALUE ... ] ]
+
+Like the insert method on an existing record, this method orders a package
+and included services atomicaly. Pass a Tie::RefHash data structure to this
+method containing FS::cust_pkg and FS::svc_I<tablename> objects. There should
+be a better explanation of this, but until then, here's an example:
+
+ use Tie::RefHash;
+ tie %hash, 'Tie::RefHash'; #this part is important
+ %hash = (
+ $cust_pkg => [ $svc_acct ],
+ ...
+ );
+ $cust_main->order_pkgs( \%hash, 'noexport'=>1 );
+
+Currently available options are: I<noexport>
-document me. like ->insert(%cust_pkg) on an existing record
+If I<noexport> is set true, no provisioning jobs (exports) are scheduled.
+(You can schedule them later with the B<reexport> method for each
+cust_pkg object. Using the B<reexport> method on the cust_main object is not
+recommended, as existing services will also be reexported.)
=cut
@@ -327,6 +358,7 @@ sub order_pkgs {
my $self = shift;
my $cust_pkgs = shift;
my $seconds = shift;
+ my %options = @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -339,6 +371,8 @@ sub order_pkgs {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
+ local $FS::svc_Common::noexport_hack = 1 if $options{'noexport'};
+
foreach my $cust_pkg ( keys %$cust_pkgs ) {
$cust_pkg->custnum( $self->custnum );
my $error = $cust_pkg->insert;
@@ -365,6 +399,41 @@ sub order_pkgs {
''; #no error
}
+=item reexport
+
+Re-schedules all exports by calling the B<reexport> method of all associated
+packages (see L<FS::cust_pkg>). If there is an error, returns the error;
+otherwise returns false.
+
+=cut
+
+sub reexport {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $cust_pkg ( $self->ncancelled_pkgs ) {
+ my $error = $cust_pkg->reexport;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
=item delete NEW_CUSTNUM
This deletes the customer. If there is an error, returns the error, otherwise
@@ -372,7 +441,7 @@ returns false.
This will completely remove all traces of the customer record. This is not
what you want when a customer cancels service; for that, cancel all of the
-customer's packages (see L<FS::cust_pkg/cancel>).
+customer's packages (see L</cancel>).
If the customer has any uncancelled packages, you need to pass a new (valid)
customer number for those packages to be transferred to. Cancelled packages
@@ -399,19 +468,19 @@ sub delete {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- if ( qsearch( 'cust_bill', { 'custnum' => $self->custnum } ) ) {
+ if ( $self->cust_bill ) {
$dbh->rollback if $oldAutoCommit;
return "Can't delete a customer with invoices";
}
- if ( qsearch( 'cust_credit', { 'custnum' => $self->custnum } ) ) {
+ if ( $self->cust_credit ) {
$dbh->rollback if $oldAutoCommit;
return "Can't delete a customer with credits";
}
- if ( qsearch( 'cust_pay', { 'custnum' => $self->custnum } ) ) {
+ if ( $self->cust_pay ) {
$dbh->rollback if $oldAutoCommit;
return "Can't delete a customer with payments";
}
- if ( qsearch( 'cust_refund', { 'custnum' => $self->custnum } ) ) {
+ if ( $self->cust_refund ) {
$dbh->rollback if $oldAutoCommit;
return "Can't delete a customer with refunds";
}
@@ -490,6 +559,12 @@ sub replace {
local $SIG{TSTP} = 'IGNORE';
local $SIG{PIPE} = 'IGNORE';
+ if ( $self->payby eq 'COMP' && $self->payby ne $old->payby
+ && $conf->config('users-allow_comp') ) {
+ return "You are not permitted to create complimentary accounts."
+ unless grep { $_ eq getotaker } $conf->config('users-allow_comp');
+ }
+
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
@@ -603,7 +678,7 @@ sub check {
|| $self->ut_numbern('referral_custnum')
;
#barf. need message catalogs. i18n. etc.
- $error .= "Please select a advertising source."
+ $error .= "Please select an advertising source."
if $error =~ /^Illegal or empty \(numeric\) refnum: /;
return $error if $error;
@@ -722,6 +797,21 @@ sub check {
or return gettext('invalid_card'); # . ": ". $self->payinfo;
return gettext('unknown_card_type')
if cardtype($self->payinfo) eq "Unknown";
+ if ( defined $self->dbdef_table->column('paycvv') ) {
+ if ( length($self->paycvv) ) {
+ if ( cardtype($self->payinfo) eq 'American Express card' ) {
+ $self->paycvv =~ /^(\d{4})$/
+ or return "CVV2 (CID) for American Express cards is four digits.";
+ $self->paycvv($1);
+ } else {
+ $self->paycvv =~ /^(\d{3})$/
+ or return "CVV2 (CVC2/CID) is three digits.";
+ $self->paycvv($1);
+ }
+ } else {
+ $self->paycvv('');
+ }
+ }
} elsif ( $self->payby eq 'CHEK' || $self->payby eq 'DCHK' ) {
@@ -730,6 +820,7 @@ sub check {
$payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account@aba';
$payinfo = "$1\@$2";
$self->payinfo($payinfo);
+ $self->paycvv('') if $self->dbdef_table->column('paycvv');
} elsif ( $self->payby eq 'LECB' ) {
@@ -738,16 +829,24 @@ sub check {
$payinfo =~ /^1?(\d{10})$/ or return 'invalid btn billing telephone number';
$payinfo = $1;
$self->payinfo($payinfo);
+ $self->paycvv('') if $self->dbdef_table->column('paycvv');
} elsif ( $self->payby eq 'BILL' ) {
$error = $self->ut_textn('payinfo');
return "Illegal P.O. number: ". $self->payinfo if $error;
+ $self->paycvv('') if $self->dbdef_table->column('paycvv');
} elsif ( $self->payby eq 'COMP' ) {
+ if ( !$self->custnum && $conf->config('users-allow_comp') ) {
+ return "You are not permitted to create complimentary accounts."
+ unless grep { $_ eq getotaker } $conf->config('users-allow_comp');
+ }
+
$error = $self->ut_textn('payinfo');
return "Illegal comp account issuer: ". $self->payinfo if $error;
+ $self->paycvv('') if $self->dbdef_table->column('paycvv');
} elsif ( $self->payby eq 'PREPAY' ) {
@@ -758,6 +857,7 @@ sub check {
return "Illegal prepayment identifier: ". $self->payinfo if $error;
return "Unknown prepayment identifier"
unless qsearchs('prepay_credit', { 'identifier' => $self->payinfo } );
+ $self->paycvv('') if $self->dbdef_table->column('paycvv');
}
@@ -780,7 +880,7 @@ sub check {
if !$import && ( $y<$nowy || ( $y==$nowy && $1<$nowm ) );
}
- if ( $self->payname eq '' && $self->payby ne 'CHEK' &&
+ if ( $self->payname eq '' && $self->payby !~ /^(CHEK|DCHK)$/ &&
( ! $conf->exists('require_cardname')
|| $self->payby !~ /^(CARD|DCRD)$/ )
) {
@@ -794,7 +894,7 @@ sub check {
$self->tax =~ /^(Y?)$/ or return "Illegal tax: ". $self->tax;
$self->tax($1);
- $self->otaker(getotaker);
+ $self->otaker(getotaker) unless $self->otaker;
#warn "AFTER: \n". $self->_dump;
@@ -902,16 +1002,21 @@ sub suspend {
grep { $_->suspend } $self->unsuspended_pkgs;
}
-=item cancel
+=item cancel [ OPTION => VALUE ... ]
Cancels all uncancelled packages (see L<FS::cust_pkg>) for this customer.
+
+Available options are: I<quiet>
+
+I<quiet> can be set true to supress email cancellation notices.
+
Always returns a list: an empty list on success or a list of errors.
=cut
sub cancel {
my $self = shift;
- grep { $_->cancel } $self->ncancelled_pkgs;
+ grep { $_ } map { $_->cancel(@_) } $self->ncancelled_pkgs;
}
=item agent
@@ -932,15 +1037,19 @@ conjunction with the collect method.
Options are passed as name-value pairs.
-The only currently available option is `time', which bills the customer as if
-it were that time. It is specified as a UNIX timestamp; see
-L<perlfunc/"time">). Also see L<Time::Local> and L<Date::Parse> for conversion
-functions. For example:
+Currently available options are:
+
+resetup - if set true, re-charges setup fees.
+
+time - bills the customer as if it were that time. Specified as a UNIX
+timestamp; see L<perlfunc/"time">). Also see L<Time::Local> and
+L<Date::Parse> for conversion functions. For example:
use Date::Parse;
...
$cust_main->bill( 'time' => str2time('April 20th, 2001') );
+
If there is an error, returns the error, otherwise returns false.
=cut
@@ -997,7 +1106,7 @@ sub bill {
# bill setup
my $setup = 0;
- unless ( $cust_pkg->setup ) {
+ if ( !$cust_pkg->setup || $options{'resetup'} ) {
my $setup_prog = $part_pkg->getfield('setup');
$setup_prog =~ /^(.*)$/ or do {
$dbh->rollback if $oldAutoCommit;
@@ -1017,14 +1126,14 @@ sub bill {
return "Error eval-ing part_pkg->setup pkgpart ". $part_pkg->pkgpart.
"(expression $setup_prog): $@";
}
- $cust_pkg->setfield('setup',$time);
+ $cust_pkg->setfield('setup', $time) unless $cust_pkg->setup;
$cust_pkg_mod_flag=1;
}
#bill recurring fee
my $recur = 0;
my $sdate;
- if ( $part_pkg->getfield('freq') > 0 &&
+ if ( $part_pkg->getfield('freq') ne '0' &&
! $cust_pkg->getfield('susp') &&
( $cust_pkg->getfield('bill') || 0 ) <= $time
) {
@@ -1062,8 +1171,19 @@ sub bill {
$cust_pkg->last_bill($sdate)
if $cust_pkg->dbdef_table->column('last_bill');
- $mon += $part_pkg->freq;
- until ( $mon < 12 ) { $mon -= 12; $year++; }
+ if ( $part_pkg->freq =~ /^\d+$/ ) {
+ $mon += $part_pkg->freq;
+ until ( $mon < 12 ) { $mon -= 12; $year++; }
+ } elsif ( $part_pkg->freq =~ /^(\d+)w$/ ) {
+ my $weeks = $1;
+ $mday += $weeks * 7;
+ } elsif ( $part_pkg->freq =~ /^(\d+)d$/ ) {
+ my $days = $1;
+ $mday += $days;
+ } else {
+ $dbh->rollback if $oldAutoCommit;
+ return "unparsable frequency: ". $part_pkg->freq;
+ }
$cust_pkg->setfield('bill',
timelocal_nocheck($sec,$min,$hour,$mday,$mon,$year));
$cust_pkg_mod_flag = 1;
@@ -1073,7 +1193,6 @@ sub bill {
warn "\$recur is undefined" unless defined($recur);
warn "\$cust_pkg->bill is undefined" unless defined($cust_pkg->bill);
- my $taxable_charged = 0;
if ( $cust_pkg_mod_flag ) {
$error=$cust_pkg->replace($old_cust_pkg);
if ( $error ) { #just in case
@@ -1082,15 +1201,15 @@ sub bill {
}
$setup = sprintf( "%.2f", $setup );
$recur = sprintf( "%.2f", $recur );
- if ( $setup < 0 ) {
+ if ( $setup < 0 && ! $conf->exists('allow_negative_charges') ) {
$dbh->rollback if $oldAutoCommit;
return "negative setup $setup for pkgnum ". $cust_pkg->pkgnum;
}
- if ( $recur < 0 ) {
+ if ( $recur < 0 && ! $conf->exists('allow_negative_charges') ) {
$dbh->rollback if $oldAutoCommit;
return "negative recur $recur for pkgnum ". $cust_pkg->pkgnum;
}
- if ( $setup > 0 || $recur > 0 ) {
+ if ( $setup != 0 || $recur != 0 ) {
my $cust_bill_pkg = new FS::cust_bill_pkg ({
'pkgnum' => $cust_pkg->pkgnum,
'setup' => $setup,
@@ -1102,88 +1221,113 @@ sub bill {
push @cust_bill_pkg, $cust_bill_pkg;
$total_setup += $setup;
$total_recur += $recur;
- $taxable_charged += $setup
- unless $part_pkg->setuptax =~ /^Y$/i;
- $taxable_charged += $recur
- unless $part_pkg->recurtax =~ /^Y$/i;
-
- unless ( $self->tax =~ /Y/i
- || $self->payby eq 'COMP'
- || $taxable_charged == 0 ) {
-
- my $cust_main_county = qsearchs('cust_main_county',{
- 'state' => $self->state,
- 'county' => $self->county,
- 'country' => $self->country,
- 'taxclass' => $part_pkg->taxclass,
- } );
- $cust_main_county ||= qsearchs('cust_main_county',{
- 'state' => $self->state,
- 'county' => $self->county,
- 'country' => $self->country,
- 'taxclass' => '',
- } );
- unless ( $cust_main_county ) {
+
+ unless ( $self->tax =~ /Y/i || $self->payby eq 'COMP' ) {
+
+ my @taxes = qsearch( 'cust_main_county', {
+ 'state' => $self->state,
+ 'county' => $self->county,
+ 'country' => $self->country,
+ 'taxclass' => $part_pkg->taxclass,
+ } );
+ unless ( @taxes ) {
+ @taxes = qsearch( 'cust_main_county', {
+ 'state' => $self->state,
+ 'county' => $self->county,
+ 'country' => $self->country,
+ 'taxclass' => '',
+ } );
+ }
+
+ #one more try at a whole-country tax rate
+ unless ( @taxes ) {
+ @taxes = qsearch( 'cust_main_county', {
+ 'state' => '',
+ 'county' => '',
+ 'country' => $self->country,
+ 'taxclass' => '',
+ } );
+ }
+
+ # maybe eliminate this entirely, along with all the 0% records
+ unless ( @taxes ) {
$dbh->rollback if $oldAutoCommit;
return
"fatal: can't find tax rate for state/county/country/taxclass ".
join('/', ( map $self->$_(), qw(state county country) ),
$part_pkg->taxclass ). "\n";
}
+
+ foreach my $tax ( @taxes ) {
+
+ my $taxable_charged = 0;
+ $taxable_charged += $setup
+ unless $part_pkg->setuptax =~ /^Y$/i
+ || $tax->setuptax =~ /^Y$/i;
+ $taxable_charged += $recur
+ unless $part_pkg->recurtax =~ /^Y$/i
+ || $tax->recurtax =~ /^Y$/i;
+ next unless $taxable_charged;
+
+ if ( $tax->exempt_amount > 0 ) {
+ my ($mon,$year) = (localtime($sdate) )[4,5];
+ $mon++;
+ my $freq = $part_pkg->freq || 1;
+ if ( $freq !~ /(\d+)$/ ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "daily/weekly package definitions not (yet?)".
+ " compatible with monthly tax exemptions";
+ }
+ my $taxable_per_month = sprintf("%.2f", $taxable_charged / $freq );
+ foreach my $which_month ( 1 .. $freq ) {
+ my %hash = (
+ 'custnum' => $self->custnum,
+ 'taxnum' => $tax->taxnum,
+ 'year' => 1900+$year,
+ 'month' => $mon++,
+ );
+ #until ( $mon < 12 ) { $mon -= 12; $year++; }
+ until ( $mon < 13 ) { $mon -= 12; $year++; }
+ my $cust_tax_exempt =
+ qsearchs('cust_tax_exempt', \%hash)
+ || new FS::cust_tax_exempt( { %hash, 'amount' => 0 } );
+ my $remaining_exemption = sprintf("%.2f",
+ $tax->exempt_amount - $cust_tax_exempt->amount );
+ if ( $remaining_exemption > 0 ) {
+ my $addl = $remaining_exemption > $taxable_per_month
+ ? $taxable_per_month
+ : $remaining_exemption;
+ $taxable_charged -= $addl;
+ my $new_cust_tax_exempt = new FS::cust_tax_exempt ( {
+ $cust_tax_exempt->hash,
+ 'amount' =>
+ sprintf("%.2f", $cust_tax_exempt->amount + $addl),
+ } );
+ $error = $new_cust_tax_exempt->exemptnum
+ ? $new_cust_tax_exempt->replace($cust_tax_exempt)
+ : $new_cust_tax_exempt->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "fatal: can't update cust_tax_exempt: $error";
+ }
+
+ } # if $remaining_exemption > 0
+
+ } #foreach $which_month
+
+ } #if $tax->exempt_amount
+
+ $taxable_charged = sprintf( "%.2f", $taxable_charged);
+
+ #$tax += $taxable_charged * $cust_main_county->tax / 100
+ $tax{ $tax->taxname || 'Tax' } +=
+ $taxable_charged * $tax->tax / 100
+
+ } #foreach my $tax ( @taxes )
+
+ } #unless $self->tax =~ /Y/i || $self->payby eq 'COMP'
- if ( $cust_main_county->exempt_amount ) {
- my ($mon,$year) = (localtime($sdate) )[4,5];
- $mon++;
- my $freq = $part_pkg->freq || 1;
- my $taxable_per_month = sprintf("%.2f", $taxable_charged / $freq );
- foreach my $which_month ( 1 .. $freq ) {
- my %hash = (
- 'custnum' => $self->custnum,
- 'taxnum' => $cust_main_county->taxnum,
- 'year' => 1900+$year,
- 'month' => $mon++,
- );
- #until ( $mon < 12 ) { $mon -= 12; $year++; }
- until ( $mon < 13 ) { $mon -= 12; $year++; }
- my $cust_tax_exempt =
- qsearchs('cust_tax_exempt', \%hash)
- || new FS::cust_tax_exempt( { %hash, 'amount' => 0 } );
- my $remaining_exemption = sprintf("%.2f",
- $cust_main_county->exempt_amount - $cust_tax_exempt->amount );
- if ( $remaining_exemption > 0 ) {
- my $addl = $remaining_exemption > $taxable_per_month
- ? $taxable_per_month
- : $remaining_exemption;
- $taxable_charged -= $addl;
- my $new_cust_tax_exempt = new FS::cust_tax_exempt ( {
- $cust_tax_exempt->hash,
- 'amount' => sprintf("%.2f", $cust_tax_exempt->amount + $addl),
- } );
- $error = $new_cust_tax_exempt->exemptnum
- ? $new_cust_tax_exempt->replace($cust_tax_exempt)
- : $new_cust_tax_exempt->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "fatal: can't update cust_tax_exempt: $error";
- }
-
- } # if $remaining_exemption > 0
-
- } #foreach $which_month
-
- } #if $cust_main_county->exempt_amount
-
- $taxable_charged = sprintf( "%.2f", $taxable_charged);
-
- #$tax += $taxable_charged * $cust_main_county->tax / 100
- $tax{ $cust_main_county->taxname || 'Tax' } +=
- $taxable_charged * $cust_main_county->tax / 100
-
- } #unless $self->tax =~ /Y/i
- # || $self->payby eq 'COMP'
- # || $taxable_charged == 0
-
- } #if $setup > 0 || $recur > 0
+ } #if $setup != 0 || $recur != 0
} #if $cust_pkg_mod_flag
@@ -1210,21 +1354,42 @@ sub bill {
# $taxable_charged * ( $cust_main_county->getfield('tax') / 100 )
# );
- foreach my $taxname ( grep { $tax{$_} > 0 } keys %tax ) {
- my $tax = sprintf("%.2f", $tax{$taxname} );
- $charged = sprintf( "%.2f", $charged+$tax );
+ if ( dbdef->table('cust_bill_pkg')->column('itemdesc') ) { #1.5 schema
+
+ foreach my $taxname ( grep { $tax{$_} > 0 } keys %tax ) {
+ my $tax = sprintf("%.2f", $tax{$taxname} );
+ $charged = sprintf( "%.2f", $charged+$tax );
+
+ my $cust_bill_pkg = new FS::cust_bill_pkg ({
+ 'pkgnum' => 0,
+ 'setup' => $tax,
+ 'recur' => 0,
+ 'sdate' => '',
+ 'edate' => '',
+ 'itemdesc' => $taxname,
+ });
+ push @cust_bill_pkg, $cust_bill_pkg;
+ }
+
+ } else { #1.4 schema
+
+ my $tax = 0;
+ foreach ( values %tax ) { $tax += $_ };
+ $tax = sprintf("%.2f", $tax);
+ if ( $tax > 0 ) {
+ $charged = sprintf( "%.2f", $charged+$tax );
+
+ my $cust_bill_pkg = new FS::cust_bill_pkg ({
+ 'pkgnum' => 0,
+ 'setup' => $tax,
+ 'recur' => 0,
+ 'sdate' => '',
+ 'edate' => '',
+ });
+ push @cust_bill_pkg, $cust_bill_pkg;
+ }
- my $cust_bill_pkg = new FS::cust_bill_pkg ({
- 'pkgnum' => 0,
- 'setup' => $tax,
- 'recur' => 0,
- 'sdate' => '',
- 'edate' => '',
- 'itemdesc' => $taxname,
- });
- push @cust_bill_pkg, $cust_bill_pkg;
}
-# }
my $cust_bill = new FS::cust_bill ( {
'custnum' => $self->custnum,
@@ -1288,6 +1453,8 @@ report_badcard - This option is deprecated.
force_print - This option is deprecated; see the invoice events web interface.
+quiet - set true to surpress email card/ACH decline notices.
+
=cut
sub collect {
@@ -1325,24 +1492,15 @@ sub collect {
}
}
- foreach my $cust_bill ( $self->cust_bill ) {
-
- #this has to be before next's
- my $amount = sprintf( "%.2f", $balance < $cust_bill->owed
- ? $balance
- : $cust_bill->owed
- );
- $balance = sprintf( "%.2f", $balance - $amount );
-
- next unless $cust_bill->owed > 0;
+ foreach my $cust_bill ( $self->open_cust_bill ) {
# don't try to charge for the same invoice if it's already in a batch
#next if qsearchs( 'cust_pay_batch', { 'invnum' => $cust_bill->invnum } );
- warn "invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ", amount $amount, balance $balance)" if $Debug;
-
- next unless $amount > 0;
+ last if $self->balance <= 0;
+ warn "invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ")"
+ if $Debug;
foreach my $part_bill_event (
sort { $a->seconds <=> $b->seconds
@@ -1359,12 +1517,18 @@ sub collect {
'disabled' => '', } )
) {
- last unless $cust_bill->owed > 0; #don't run subsequent events if owed=0
+ last if $cust_bill->owed <= 0 # don't run subsequent events if owed<=0
+ || $self->balance <= 0; # or if balance<=0
warn "calling invoice event (". $part_bill_event->eventcode. ")\n"
if $Debug;
my $cust_main = $self; #for callback
- my $error = eval $part_bill_event->eventcode;
+
+ my $error;
+ {
+ local $realtime_bop_decline_quiet = 1 if $options{'quiet'};
+ $error = eval $part_bill_event->eventcode;
+ }
my $status = '';
my $statustext = '';
@@ -1548,9 +1712,20 @@ sub realtime_bop {
my %content;
if ( $method eq 'CC' ) {
+
$content{card_number} = $self->payinfo;
$self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
$content{expiration} = "$2/$1";
+
+ $content{cvv2} = $self->paycvv
+ if defined $self->dbdef_table->column('paycvv')
+ && length($self->paycvv);
+
+ $content{recurring_billing} = 'YES'
+ if qsearch('cust_pay', { 'custnum' => $self->custnum,
+ 'payby' => 'CARD',
+ 'payinfo' => $self->payinfo, } );
+
} elsif ( $method eq 'ECHECK' ) {
my($account_number,$routing_code) = $self->payinfo;
( $content{account_number}, $content{routing_code} ) =
@@ -1635,6 +1810,21 @@ sub realtime_bop {
}
+ #remove paycvv after initial transaction
+ #make this disable-able via a config option if anyone insists?
+ # (though that probably violates cardholder agreements)
+ if ( defined $self->dbdef_table->column('paycvv')
+ && length($self->paycvv)
+ && ! grep { $_ eq cardtype($self->payinfo) } $conf->config('cvv-save')
+ ) {
+ my $new = new FS::cust_main { $self->hash };
+ $new->paycvv('');
+ my $error = $new->replace($self);
+ if ( $error ) {
+ warn "error removing cvv: $error\n";
+ }
+ }
+
#result handling
if ( $transaction->is_success() ) {
@@ -1669,8 +1859,11 @@ sub realtime_bop {
my $perror = "$processor error: ". $transaction->error_message;
- if ( !$options{'quiet'} && $conf->exists('emaildecline')
+ if ( !$options{'quiet'} && !$realtime_bop_decline_quiet
+ && $conf->exists('emaildecline')
&& grep { $_ ne 'POST' } $self->invoicing_list
+ && ! grep { $_ eq $transaction->error_message }
+ $conf->config('emaildecline-exclude')
) {
my @templ = $conf->config('declinetemplate');
my $template = new Text::Template (
@@ -2196,6 +2389,42 @@ sub open_cust_bill {
grep { $_->owed > 0 } $self->cust_bill;
}
+=item cust_credit
+
+Returns all the credits (see L<FS::cust_credit>) for this customer.
+
+=cut
+
+sub cust_credit {
+ my $self = shift;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_credit', { 'custnum' => $self->custnum } )
+}
+
+=item cust_pay
+
+Returns all the payments (see L<FS::cust_pay>) for this customer.
+
+=cut
+
+sub cust_pay {
+ my $self = shift;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_pay', { 'custnum' => $self->custnum } )
+}
+
+=item cust_refund
+
+Returns all the refunds (see L<FS::cust_refund>) for this customer.
+
+=cut
+
+sub cust_refund {
+ my $self = shift;
+ sort { $a->_date <=> $b->_date }
+ qsearch( 'cust_refund', { 'custnum' => $self->custnum } )
+}
+
=back
=head1 SUBROUTINES
diff --git a/FS/FS/cust_main_county.pm b/FS/FS/cust_main_county.pm
index f631d8cae..76c982ae8 100644
--- a/FS/FS/cust_main_county.pm
+++ b/FS/FS/cust_main_county.pm
@@ -63,6 +63,10 @@ currently supported:
=item taxname - if defined, printed on invoices instead of "Tax"
+=item setuptax - if 'Y', this tax does not apply to setup fees
+
+=item recurtax - if 'Y', this tax does not apply to recurring fees
+
=back
=head1 METHODS
@@ -113,10 +117,38 @@ sub check {
|| $self->ut_textn('taxclass') # ...
|| $self->ut_money('exempt_amount')
|| $self->ut_textn('taxname')
+ || $self->ut_enum('setuptax', [ '', 'Y' ] )
+ || $self->ut_enum('recurtax', [ '', 'Y' ] )
|| $self->SUPER::check
;
+}
+
+sub taxname {
+ my $self = shift;
+ if ( $self->dbdef_table->column('taxname') ) {
+ return $self->setfield('taxname', $_[0]) if @_;
+ return $self->getfield('taxname');
+ }
+ return '';
+}
+
+sub setuptax {
+ my $self = shift;
+ if ( $self->dbdef_table->column('setuptax') ) {
+ return $self->setfield('setuptax', $_[0]) if @_;
+ return $self->getfield('setuptax');
+ }
+ return '';
+}
+sub recurtax {
+ my $self = shift;
+ if ( $self->dbdef_table->column('recurtax') ) {
+ return $self->setfield('recurtax', $_[0]) if @_;
+ return $self->getfield('recurtax');
+ }
+ return '';
}
=back
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index 7be115356..e1943ae2d 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -385,11 +385,23 @@ sub unapplied {
sprintf("%.2f", $amount );
}
+=item cust_main
+
+Returns the parent customer object (see L<FS::cust_main>).
+
+=cut
+
+sub cust_main {
+ my $self = shift;
+ qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
+}
+
+
=back
=head1 VERSION
-$Id: cust_pay.pm,v 1.25 2003-08-05 00:20:42 khoff Exp $
+$Id: cust_pay.pm,v 1.26 2003-09-10 10:54:46 ivan Exp $
=head1 BUGS
diff --git a/FS/FS/cust_pay_batch.pm b/FS/FS/cust_pay_batch.pm
index 1a530467c..8059f1ca2 100644
--- a/FS/FS/cust_pay_batch.pm
+++ b/FS/FS/cust_pay_batch.pm
@@ -2,7 +2,7 @@ package FS::cust_pay_batch;
use strict;
use vars qw( @ISA );
-use FS::Record;
+use FS::Record qw(dbh qsearchs);
use Business::CreditCard;
@ISA = qw( FS::Record );
@@ -188,11 +188,199 @@ sub check {
$self->SUPER::check;
}
+=item cust_main
+
+Returns the customer (see L<FS::cust_main>) for this batched credit card
+payment.
+
+=cut
+
+sub cust_main {
+ my $self = shift;
+ qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
+}
+
=back
-=head1 VERSION
+=head1 SUBROUTINES
+
+=over 4
+
+=item import_results
+
+=cut
+
+sub import_results {
+ use Time::Local;
+ use FS::cust_pay;
+ eval "use Text::CSV_XS;";
+ die $@ if $@;
+#
+ my $param = shift;
+ my $fh = $param->{'filehandle'};
+ my $format = $param->{'format'};
+ my $paybatch = $param->{'paybatch'};
+
+ my @fields;
+ my $end_condition;
+ my $end_hook;
+ my $hook;
+ my $approved_condition;
+ my $declined_condition;
+
+ if ( $format eq 'csv-td_canada_trust-merchant_pc_batch' ) {
+
+ @fields = (
+ 'paybatchnum', # Reference#: Invoice number of the transaction
+ 'paid', # Amount: Amount of the transaction. Dollars and cents
+ # with no decimal entered.
+ '', # Card Type: 0 - MCrd, 1 - Visa, 2 - AMEX, 3 - Discover,
+ # 4 - Insignia, 5 - Diners/EnRoute, 6 - JCB
+ '_date', # Transaction Date: Date the Transaction was processed
+ 'time', # Transaction Time: Time the transaction was processed
+ 'payinfo', # Card Number: Card number for the transaction
+ '', # Expiry Date: Expiry date of the card
+ '', # Auth#: Authorization number entered for force post
+ # transaction
+ 'type', # Transaction Type: 0 - purchase, 40 - refund,
+ # 20 - force post
+ 'result', # Processing Result: 3 - Approval,
+ # 4 - Declined/Amount over limit,
+ # 5 - Invalid/Expired/stolen card,
+ # 6 - Comm Error
+ '', # Terminal ID: Terminal ID used to process the transaction
+ );
+
+ $end_condition = sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0BC';
+ };
+
+ $end_hook = sub {
+ my( $hash, $total) = @_;
+ $total = sprintf("%.2f", $total);
+ my $batch_total = sprintf("%.2f", $hash->{'paybatchnum'} / 100 );
+ return "Our total $total does not match bank total $batch_total!"
+ if $total != $batch_total;
+ '';
+ };
+
+ $hook = sub {
+ my $hash = shift;
+ $hash->{'paid'} = sprintf("%.2f", $hash->{'paid'} / 100 );
+ $hash->{'_date'} = timelocal( substr($hash->{'time'}, 4, 2),
+ substr($hash->{'time'}, 2, 2),
+ substr($hash->{'time'}, 0, 2),
+ substr($hash->{'_date'}, 6, 2),
+ substr($hash->{'_date'}, 4, 2)-1,
+ substr($hash->{'_date'}, 0, 4)-1900, );
+ };
+
+ $approved_condition = sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0' && $hash->{'result'} == 3;
+ };
+
+ $declined_condition = sub {
+ my $hash = shift;
+ $hash->{'type'} eq '0' && ( $hash->{'result'} == 4
+ || $hash->{'result'} == 5 );
+ };
+
+
+ } else {
+ return "Unknown format $format";
+ }
+
+ my $csv = new Text::CSV_XS;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $total = 0;
+ my $line;
+ while ( defined($line=<$fh>) ) {
+
+ next if $line =~ /^\s*$/; #skip blank lines
-$Id: cust_pay_batch.pm,v 1.7 2003-08-05 00:20:42 khoff Exp $
+ $csv->parse($line) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "can't parse: ". $csv->error_input();
+ };
+
+ my @values = $csv->fields();
+ my %hash;
+ foreach my $field ( @fields ) {
+ my $value = shift @values;
+ next unless $field;
+ $hash{$field} = $value;
+ }
+
+ if ( &{$end_condition}(\%hash) ) {
+ my $error = &{$end_hook}(\%hash, $total);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ last;
+ }
+
+ my $cust_pay_batch =
+ qsearchs('cust_pay_batch', { 'paybatchnum' => $hash{'paybatchnum'} } );
+ unless ( $cust_pay_batch ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "unknown paybatchnum $hash{'paybatchnum'}\n";
+ }
+ my $custnum = $cust_pay_batch->custnum,
+
+ my $error = $cust_pay_batch->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error removing paybatchnum $hash{'paybatchnum'}: $error\n";
+ }
+
+ &{$hook}(\%hash);
+
+ if ( &{$approved_condition}(\%hash) ) {
+
+ my $cust_pay = new FS::cust_pay ( {
+ 'custnum' => $custnum,
+ 'payby' => 'CARD',
+ 'paybatch' => $paybatch,
+ map { $_ => $hash{$_} } (qw( paid _date payinfo )),
+ } );
+ $error = $cust_pay->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error adding payment paybatchnum $hash{'paybatchnum'}: $error\n";
+ }
+ $total += $hash{'paid'};
+
+ $cust_pay->cust_main->apply_payments;
+
+ } elsif ( &{$declined_condition}(\%hash) ) {
+
+ #this should be configurable... if anybody else ever uses batches
+ $cust_pay_batch->cust_main->suspend;
+
+ }
+
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
+=back
=head1 BUGS
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index f59b45ab1..c2182118f 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -1,8 +1,7 @@
package FS::cust_pkg;
use strict;
-use vars qw(@ISA $disable_agentcheck);
-use vars qw( $quiet );
+use vars qw(@ISA $disable_agentcheck $DEBUG);
use FS::UID qw( getotaker dbh );
use FS::Record qw( qsearch qsearchs );
use FS::Misc qw( send_email );
@@ -26,6 +25,8 @@ use FS::Conf;
@ISA = qw( FS::Record );
+$DEBUG = 0;
+
$disable_agentcheck = 0;
sub _cache {
@@ -149,7 +150,7 @@ sub insert {
return $error if $error;
my $cust_main = $self->cust_main;
- return "Unknown customer ". $self->custnum unless $cust_main;
+ return "Unknown custnum: ". $self->custnum unless $cust_main;
unless ( $disable_agentcheck ) {
my $agent = qsearchs( 'agent', { 'agentnum' => $cust_main->agentnum } );
@@ -245,25 +246,31 @@ sub check {
$self->otaker($1);
if ( $self->dbdef_table->column('manual_flag') ) {
- $self->manual_flag =~ /^([01]?)$/ or return "Illegal manual_flag";
+ $self->manual_flag('') if $self->manual_flag eq ' ';
+ $self->manual_flag =~ /^([01]?)$/
+ or return "Illegal manual_flag ". $self->manual_flag;
$self->manual_flag($1);
}
$self->SUPER::check;
}
-=item cancel
+=item cancel [ OPTION => VALUE ... ]
Cancels and removes all services (see L<FS::cust_svc> and L<FS::part_svc>)
in this package, then cancels the package itself (sets the cancel field to
now).
+Available options are: I<quiet>
+
+I<quiet> can be set true to supress email cancellation notices.
+
If there is an error, returns the error, otherwise returns false.
=cut
sub cancel {
- my $self = shift;
+ my( $self, %options ) = @_;
my $error;
local $SIG{HUP} = 'IGNORE';
@@ -304,7 +311,7 @@ sub cancel {
my $conf = new FS::Conf;
my @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list;
- if ( !$quiet && $conf->exists('emailcancel') && @invoicing_list ) {
+ if ( !$options{'quiet'} && $conf->exists('emailcancel') && @invoicing_list ) {
my $conf = new FS::Conf;
my $error = send_email(
'from' => $conf->config('invoice_from'),
@@ -609,7 +616,7 @@ sub attribute_since_sqlradacct {
Transfers as many services as possible from this package to another package.
The destination package must already exist. Services are moved only if
-the destination allows services with the correct I<svcnum> (not svcdb).
+the destination allows services with the correct I<svcpart> (not svcdb).
Any services that can't be moved remain in the original package.
Returns an error, if there is one; otherwise, returns the number of services
@@ -660,6 +667,41 @@ sub transfer {
return $remaining;
}
+=item reexport
+
+=cut
+
+sub reexport {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $cust_svc ( $self->cust_svc ) {
+ #false laziness w/svc_Common::insert
+ my $svc_x = $cust_svc->svc_x;
+ foreach my $part_export ( $cust_svc->part_svc->part_export ) {
+ my $error = $part_export->export_insert($svc_x);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+ '';
+
+}
+
=back
=head1 SUBROUTINES
@@ -686,13 +728,16 @@ newly-created cust_pkg objects.
=cut
sub order {
-
- # Rewritten to make use of the transfer() method, and in general
- # to not suck so badly.
-
my ($custnum, $pkgparts, $remove_pkgnum, $return_cust_pkg) = @_;
# Transactionize this whole mess
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm
index 7aa311ba5..0d8a12114 100644
--- a/FS/FS/cust_svc.pm
+++ b/FS/FS/cust_svc.pm
@@ -231,7 +231,7 @@ sub check {
});
return "Already ". scalar(@cust_svc). " ". $part_svc->svc.
" services for pkgnum ". $self->pkgnum
- if scalar(@cust_svc) >= $quantity && (!$ignore_quantity || !$quantity);
+ if scalar(@cust_svc) >= $quantity && !$ignore_quantity;
}
$self->SUPER::check;
@@ -281,10 +281,15 @@ sub label {
if ( $svcdb eq 'svc_acct' ) {
$tag = $svc_x->email;
} elsif ( $svcdb eq 'svc_forward' ) {
- my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $svc_x->srcsvc } );
- $tag = $svc_acct->email. '->';
+ if ( $svc_x->srcsvc ) {
+ my $svc_acct = $svc_x->srcsvc_acct;
+ $tag = $svc_acct->email;
+ } else {
+ $tag = $svc_x->src;
+ }
+ $tag .= '->';
if ( $svc_x->dstsvc ) {
- $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $svc_x->dstsvc } );
+ my $svc_acct = $svc_x->dstsvc_acct;
$tag .= $svc_acct->email;
} else {
$tag .= $svc_x->dst;
@@ -296,6 +301,8 @@ sub label {
$tag = $domain->zone;
} elsif ( $svcdb eq 'svc_broadband' ) {
$tag = $svc_x->ip_addr;
+ } elsif ( $svcdb eq 'svc_external' ) {
+ $tag = $svc_x->id. ': '. $svc_x->title;
} else {
cluck "warning: asked for label of unsupported svcdb; using svcnum";
$tag = $svc_x->getfield('svcnum');
@@ -353,15 +360,20 @@ for records where B<svcdb> is not "svc_acct".
sub seconds_since_sqlradacct {
my($self, $start, $end) = @_;
- my $username = $self->svc_x->username;
+ my $svc_x = $self->svc_x;
- my @part_export = $self->part_svc->part_export('sqlradius')
- or die "no sqlradius export configured for this service type";
+ my @part_export = $self->part_svc->part_export('sqlradius');
+ push @part_export, $self->part_svc->part_export('sqlradius_withdomain');
+ die "no sqlradius or sqlradius_withdomain export configured for this".
+ "service type"
+ unless @part_export;
#or return undef;
my $seconds = 0;
foreach my $part_export ( @part_export ) {
+ next if $part_export->option('ignore_accounting');
+
my $dbh = DBI->connect( map { $part_export->option($_) }
qw(datasrc username password) )
or die "can't connect to sqlradius database: ". $DBI::errstr;
@@ -378,6 +390,15 @@ sub seconds_since_sqlradacct {
$str2time = 'extract(epoch from ';
}
+ my $username;
+ if ( $part_export->exporttype eq 'sqlradius' ) {
+ $username = $svc_x->username;
+ } elsif ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
+ $username = $svc_x->email;
+ } else {
+ die 'unknown exporttype '. $part_export->exporttype;
+ }
+
my $query;
#find closed sessions completely within the given range
@@ -456,16 +477,21 @@ for records where B<svcdb> is not "svc_acct".
sub attribute_since_sqlradacct {
my($self, $start, $end, $attrib) = @_;
- my $username = $self->svc_x->username;
+ my $svc_x = $self->svc_x;
- my @part_export = $self->part_svc->part_export('sqlradius')
- or die "no sqlradius export configured for this service type";
+ my @part_export = $self->part_svc->part_export('sqlradius');
+ push @part_export, $self->part_svc->part_export('sqlradius_withdomain');
+ die "no sqlradius or sqlradius_withdomain export configured for this".
+ "service type"
+ unless @part_export;
#or return undef;
my $sum = 0;
foreach my $part_export ( @part_export ) {
+ next if $part_export->option('ignore_accounting');
+
my $dbh = DBI->connect( map { $part_export->option($_) }
qw(datasrc username password) )
or die "can't connect to sqlradius database: ". $DBI::errstr;
@@ -482,6 +508,15 @@ sub attribute_since_sqlradacct {
$str2time = 'extract(epoch from ';
}
+ my $username;
+ if ( $part_export->exporttype eq 'sqlradius' ) {
+ $username = $svc_x->username;
+ } elsif ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
+ $username = $svc_x->email;
+ } else {
+ die 'unknown exporttype '. $part_export->exporttype;
+ }
+
my $sth = $dbh->prepare("SELECT SUM($attrib)
FROM radacct
WHERE UserName = ?
@@ -499,6 +534,62 @@ sub attribute_since_sqlradacct {
}
+=item get_session_history_sqlradacct TIMESTAMP_START TIMESTAMP_END
+
+See L<FS::svc_acct/get_session_history_sqlradacct>. Equivalent to
+$cust_svc->svc_x->get_session_history_sqlradacct, but more efficient.
+Meaningless for records where B<svcdb> is not "svc_acct".
+
+=cut
+
+sub get_session_history {
+ my($self, $start, $end, $attrib) = @_;
+
+ my $username = $self->svc_x->username;
+
+ my @part_export = $self->part_svc->part_export('sqlradius')
+ or die "no sqlradius export configured for this service type";
+ #or return undef;
+
+ my @sessions = ();
+
+ foreach my $part_export ( @part_export ) {
+
+ my $dbh = DBI->connect( map { $part_export->option($_) }
+ qw(datasrc username password) )
+ or die "can't connect to sqlradius database: ". $DBI::errstr;
+
+ #select a unix time conversion function based on database type
+ my $str2time;
+ if ( $dbh->{Driver}->{Name} eq 'mysql' ) {
+ $str2time = 'UNIX_TIMESTAMP(';
+ } elsif ( $dbh->{Driver}->{Name} eq 'Pg' ) {
+ $str2time = 'EXTRACT( EPOCH FROM ';
+ } else {
+ warn "warning: unknown database type ". $dbh->{Driver}->{Name}.
+ "; guessing how to convert to UNIX timestamps";
+ $str2time = 'extract(epoch from ';
+ }
+
+ my @fields = qw( acctstarttime acctstoptime acctsessiontime
+ acctinputoctets acctoutputoctets framedipaddress );
+
+ my $sth = $dbh->prepare('SELECT '. join(', ', @fields).
+ " FROM radacct
+ WHERE UserName = ?
+ AND $str2time AcctStopTime ) >= ?
+ AND $str2time AcctStopTime ) <= ?
+ ORDER BY AcctStartTime DESC
+ ") or die $dbh->errstr;
+ $sth->execute($username, $start, $end) or die $sth->errstr;
+
+ push @sessions, map { { %$_ } } @{ $sth->fetchall_arrayref({}) };
+
+ }
+ \@sessions
+
+}
+
=back
=head1 BUGS
diff --git a/FS/FS/part_bill_event.pm b/FS/FS/part_bill_event.pm
index 9e5d82161..86f929424 100644
--- a/FS/FS/part_bill_event.pm
+++ b/FS/FS/part_bill_event.pm
@@ -160,6 +160,12 @@ sub check {
join("\n", $conf->config('invoice_template') )
);
}
+ unless ( $conf->exists("invoice_latex_$name") ) {
+ $conf->set(
+ "invoice_latex_$name" =>
+ join("\n", $conf->config('invoice_latex') )
+ );
+ }
}
$self->SUPER::check;
diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index ab0a4b566..8423da299 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -274,10 +274,6 @@ sub check {
;
return $error if $error;
- $self->machine =~ /^([\w\-\.]*)$/
- or return "Illegal machine: ". $self->machine;
- $self->machine($1);
-
$self->nodomain =~ /^(Y?)$/ or return "Illegal nodomain: ". $self->nodomain;
$self->nodomain($1);
@@ -472,18 +468,22 @@ sub _export_delete {
return "_export_delete: unknown export type ". $self->exporttype;
}
-#fallbacks providing null operations
+#call svcdb-specific fallbacks
sub _export_suspend {
my $self = shift;
#warn "warning: _export_suspened unimplemented for". ref($self);
- '';
+ my $svc_x = shift;
+ my $new = $svc_x->clone_suspended;
+ $self->_export_replace( $new, $svc_x );
}
sub _export_unsuspend {
my $self = shift;
#warn "warning: _export_unsuspend unimplemented for ". ref($self);
- '';
+ my $svc_x = shift;
+ my $old = $svc_x->clone_kludge_unsuspend;
+ $self->_export_replace( $svc_x, $old );
}
=back
@@ -580,13 +580,13 @@ tie my %shellcommands_options, 'Tie::IxHash',
type =>'checkbox',
},
'suspend' => { label=>'Suspension command',
- default=>'',
+ default=>'usermod -L $username',
},
'suspend_stdin' => { label=>'Suspension command STDIN',
default=>'',
},
'unsuspend' => { label=>'Unsuspension command',
- default=>'',
+ default=>'usermod -U $username',
},
'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
default=>'',
@@ -681,7 +681,7 @@ tie my %router_options, 'Tie::IxHash',
;
tie my %domain_shellcommands_options, 'Tie::IxHash',
- 'user' => { lable=>'Remote username', default=>'root' },
+ 'user' => { label=>'Remote username', default=>'root' },
'useradd' => { label=>'Insert command',
default=>'',
},
@@ -702,12 +702,20 @@ tie my %sqlradius_options, 'Tie::IxHash',
'datasrc' => { label=>'DBI data source ' },
'username' => { label=>'Database username' },
'password' => { label=>'Database password' },
+ 'ignore_accounting' => {
+ type => 'checkbox',
+ label=>'Ignore accounting records from this database'
+ },
;
tie my %sqlradius_withdomain_options, 'Tie::IxHash',
'datasrc' => { label=>'DBI data source ' },
'username' => { label=>'Database username' },
'password' => { label=>'Database password' },
+ 'ignore_accounting' => {
+ type => 'checkbox',
+ label=>'Ignore accounting records from this database'
+ },
;
tie my %cyrus_options, 'Tie::IxHash',
@@ -741,6 +749,41 @@ tie my %vpopmail_options, 'Tie::IxHash',
},
;
+tie my %communigate_pro_options, 'Tie::IxHash',
+ 'port' => { label=>'Port number', default=>'106', },
+ 'login' => { label=>'The administrator account name. The name can contain a domain part.', },
+ 'password' => { label=>'The administrator account password.', },
+ 'accountType' => { label=>'Type for newly-created accounts',
+ type=>'select',
+ options=>[qw( MultiMailbox TextMailbox MailDirMailbox )],
+ default=>'MultiMailbox',
+ },
+ 'externalFlag' => { label=> 'Create accounts with an external (visible for legacy mailers) INBOX.',
+ type=>'checkbox',
+ },
+ 'AccessModes' => { label=>'Access modes',
+ default=>'Mail POP IMAP PWD WebMail WebSite',
+ },
+;
+
+tie my %communigate_pro_singledomain_options, 'Tie::IxHash',
+ 'port' => { label=>'Port number', default=>'106', },
+ 'login' => { label=>'The administrator account name. The name can contain a domain part.', },
+ 'password' => { label=>'The administrator account password.', },
+ 'domain' => { label=>'Domain', },
+ 'accountType' => { label=>'Type for newly-created accounts',
+ type=>'select',
+ options=>[qw( MultiMailbox TextMailbox MailDirMailbox )],
+ default=>'MultiMailbox',
+ },
+ 'externalFlag' => { label=> 'Create accounts with an external (visible for legacy mailers) INBOX.',
+ type=>'checkbox',
+ },
+ 'AccessModes' => { label=>'Access modes',
+ default=>'Mail POP IMAP PWD WebMail WebSite',
+ },
+;
+
tie my %bind_options, 'Tie::IxHash',
#'machine' => { label=>'named machine' },
'named_conf' => { label => 'named.conf location',
@@ -852,7 +895,7 @@ tie my %ldap_options, 'Tie::IxHash',
;
tie my %forward_shellcommands_options, 'Tie::IxHash',
- 'user' => { lable=>'Remote username', default=>'root' },
+ 'user' => { label=>'Remote username', default=>'root' },
'useradd' => { label=>'Insert command',
default=>'',
},
@@ -864,6 +907,13 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
},
;
+tie my %postfix_options, 'Tie::IxHash',
+ 'user' => { label=>'Remote username', default=>'root' },
+ 'aliases' => { label=>'aliases file location', default=>'/etc/aliases' },
+ 'virtual' => { label=>'virtual file location', default=>'/etc/postfix/virtual' },
+ 'mydomain' => { label=>'local domain', default=>'' },
+;
+
#export names cannot have dashes...
%exports = (
'svc_acct' => {
@@ -896,7 +946,7 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
'desc' => 'Real-time export via remote SSH (i.e. useradd, userdel, etc.)',
'options' => \%shellcommands_options,
'nodomain' => 'Y',
- 'notes' => 'Run remote commands via SSH. Usernames are considered unique (also see shellcommands_withdomain). You probably want this if the commands you are running will not accept a domain as a parameter. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.<BR><BR>Use these buttons for some useful presets:<UL><LI><INPUT TYPE="button" VALUE="Linux/NetBSD" onClick=\'this.form.useradd.value = "useradd -c $finger -d $dir -m -s $shell -u $uid -p $crypt_password $username"; this.form.useradd_stdin.value = ""; this.form.userdel.value = "userdel -r $username"; this.form.userdel_stdin.value=""; this.form.usermod.value = "usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username"; this.form.usermod_stdin.value = "";\'><LI><INPUT TYPE="button" VALUE="FreeBSD" onClick=\'this.form.useradd.value = "pw useradd $username -d $dir -m -s $shell -u $uid -g $gid -c $finger -h 0"; this.form.useradd_stdin.value = "$_password\n"; this.form.userdel.value = "pw userdel $username -r"; this.form.userdel_stdin.value=""; this.form.usermod.value = "pw usermod $old_username -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -c $new_finger -h 0"; this.form.usermod_stdin.value = "$new__password\n";\'><LI><INPUT TYPE="button" VALUE="Just maintain directories (use with sysvshell or bsdshell)" onClick=\'this.form.useradd.value = "cp -pr /etc/skel $dir; chown -R $uid.$gid $dir"; this.form.useradd_stdin.value = ""; this.form.usermod.value = "[ -d $old_dir ] && mv $old_dir $new_dir || ( chmod u+t $old_dir; mkdir $new_dir; cd $old_dir; find . -depth -print | cpio -pdm $new_dir; chmod u-t $new_dir; chown -R $new_uid.$new_gid $new_dir; rm -rf $old_dir )"; this.form.usermod_stdin.value = ""; this.form.userdel.value = "rm -rf $dir"; this.form.userdel_stdin.value="";\'></UL>The following variables are available for interpolation (prefixed with new_ or old_ for replace operations): <UL><LI><code>$username</code><LI><code>$_password</code><LI><code>$quoted_password</code> - unencrypted password quoted for the shell<LI><code>$crypt_password</code> - encrypted password<LI><code>$uid</code><LI><code>$gid</code><LI><code>$finger</code> - GECOS, already quoted for the shell (do not add additional quotes)<LI><code>$dir</code> - home directory<LI><code>$shell</code><LI><code>$quota</code><LI>All other fields in <a href="../docs/schema.html#svc_acct">svc_acct</a> are also available.</UL>',
+ 'notes' => 'Run remote commands via SSH. Usernames are considered unique (also see shellcommands_withdomain). You probably want this if the commands you are running will not accept a domain as a parameter. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.<BR><BR>Use these buttons for some useful presets:<UL><LI><INPUT TYPE="button" VALUE="Linux" onClick=\'this.form.useradd.value = "useradd -c $finger -d $dir -m -s $shell -u $uid -p $crypt_password $username"; this.form.useradd_stdin.value = ""; this.form.userdel.value = "userdel -r $username"; this.form.userdel_stdin.value=""; this.form.usermod.value = "usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username"; this.form.usermod_stdin.value = ""; this.form.suspend.value = "usermod -L $username"; this.form.suspend_stdin.value=""; this.form.unsuspend.value = "usermod -U $username"; this.form.unsuspend_stdin.value="";\'><LI><INPUT TYPE="button" VALUE="FreeBSD" onClick=\'this.form.useradd.value = "lockf /etc/passwd.lock pw useradd $username -d $dir -m -s $shell -u $uid -g $gid -c $finger -h 0"; this.form.useradd_stdin.value = "$_password\n"; this.form.userdel.value = "lockf /etc/passwd.lock pw userdel $username -r"; this.form.userdel_stdin.value=""; this.form.usermod.value = "lockf /etc/passwd.lock pw usermod $old_username -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -c $new_finger -h 0"; this.form.usermod_stdin.value = "$new__password\n"; this.form.suspend.value = "lockf /etc/passwd.lock pw lock $username"; this.form.suspend_stdin.value=""; this.form.unsuspend.value = "lockf /etc/passwd.lock pw unlock $username"; this.form.unsuspend_stdin.value="";\'> Note: On FreeBSD, due to deficient locking in pw(1), you must disable the chpass(1), chsh(1), chfn(1), passwd(1), and vipw(1) commands, or replace them with wrappers that prepend "lockf /etc/passwd.lock". Alternatively, apply the patch in <A HREF="http://www.freebsd.org/cgi/query-pr.cgi?pr=23501">FreeBSD PR#23501</A> and remove the "lockf /etc/passwd.lock" from these default commands.<LI><INPUT TYPE="button" VALUE="NetBSD/OpenBSD" onClick=\'this.form.useradd.value = "useradd -c $finger -d $dir -m -s $shell -u $uid -p $crypt_password $username"; this.form.useradd_stdin.value = ""; this.form.userdel.value = "userdel -r $username"; this.form.userdel_stdin.value=""; this.form.usermod.value = "usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username"; this.form.usermod_stdin.value = ""; this.form.suspend.value = ""; this.form.suspend_stdin.value=""; this.form.unsuspend.value = ""; this.form.unsuspend_stdin.value="";\'><LI><INPUT TYPE="button" VALUE="Just maintain directories (use with sysvshell or bsdshell)" onClick=\'this.form.useradd.value = "cp -pr /etc/skel $dir; chown -R $uid.$gid $dir"; this.form.useradd_stdin.value = ""; this.form.usermod.value = "[ -d $old_dir ] && mv $old_dir $new_dir || ( chmod u+t $old_dir; mkdir $new_dir; cd $old_dir; find . -depth -print | cpio -pdm $new_dir; chmod u-t $new_dir; chown -R $new_uid.$new_gid $new_dir; rm -rf $old_dir )"; this.form.usermod_stdin.value = ""; this.form.userdel.value = "rm -rf $dir"; this.form.userdel_stdin.value=""; this.form.suspend.value = ""; this.form.suspend_stdin.value=""; this.form.unsuspend.value = ""; this.form.unsuspend_stdin.value="";\'></UL>The following variables are available for interpolation (prefixed with new_ or old_ for replace operations): <UL><LI><code>$username</code><LI><code>$_password</code><LI><code>$quoted_password</code> - unencrypted password quoted for the shell<LI><code>$crypt_password</code> - encrypted password<LI><code>$uid</code><LI><code>$gid</code><LI><code>$finger</code> - GECOS, already quoted for the shell (do not add additional quotes)<LI><code>$dir</code> - home directory<LI><code>$shell</code><LI><code>$quota</code><LI>All other fields in <a href="../docs/schema.html#svc_acct">svc_acct</a> are also available.</UL>',
},
'shellcommands_withdomain' => {
@@ -912,17 +962,17 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
},
'sqlradius' => {
- 'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS)',
+ 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS, Radiator)',
'options' => \%sqlradius_options,
'nodomain' => 'Y',
- 'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a> or <a href="http://radius.innercite.com/">ICRADIUS</a>. This export does not export RADIUS realms (see also sqlradius_withdomain). An existing RADIUS database will be updated in realtime, but you can use <a href="../docs/man/bin/freeside-sqlradius-reset">freeside-sqlradius-reset</a> to delete the entire RADIUS database and repopulate the tables from the Freeside database. See the <a href="http://search.cpan.org/doc/TIMB/DBI/DBI.pm">DBI documentation</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">documentation for your DBD</a> for the exact syntax of a DBI data source.',
+ 'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a>, <a href="http://radius.innercite.com/">ICRADIUS</a> or <a href="http://www.open.com.au/radiator/">Radiator</a>. This export does not export RADIUS realms (see also sqlradius_withdomain). An existing RADIUS database will be updated in realtime, but you can use <a href="../docs/man/bin/freeside-sqlradius-reset">freeside-sqlradius-reset</a> to delete the entire RADIUS database and repopulate the tables from the Freeside database. See the <a href="http://search.cpan.org/doc/TIMB/DBI/DBI.pm#connect">DBI documentation</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">documentation for your DBD</a> for the exact syntax of a DBI data source.<ul><li>Using FreeRADIUS 0.9.0 with the PostgreSQL backend, the db_postgresql.sql schema and postgresql.conf queries contain incompatible changes. This is fixed in 0.9.1. Only new installs with 0.9.0 and PostgreSQL are affected - upgrades and other database backends and versions are unaffected.<li>Using ICRADIUS, add a dummy "op" column to your database: <blockquote><code>ALTER&nbsp;TABLE&nbsp;radcheck&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'<br>ALTER&nbsp;TABLE&nbsp;radreply&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'<br>ALTER&nbsp;TABLE&nbsp;radgroupcheck&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'<br>ALTER&nbsp;TABLE&nbsp;radgroupreply&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'</code></blockquote><li>Using Radiator, see the <a href="http://www.open.com.au/radiator/faq.html#38">Radiator FAQ</a> for configuration information.</ul>',
},
'sqlradius_withdomain' => {
- 'desc' => 'Real-time export to SQL-backed RADIUS (ICRADIUS, FreeRADIUS) with realms',
+ 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS, Radiator) with realms',
'options' => \%sqlradius_withdomain_options,
'nodomain' => '',
- 'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a> or <a href="http://radius.innercite.com/">ICRADIUS</a>. This export exports domains to RADIUS realms (see also sqlradius). An existing RADIUS database will be updated in realtime, but you can use <a href="../docs/man/bin/freeside-sqlradius-reset">freeside-sqlradius-reset</a> to delete the entire RADIUS database and repopulate the tables from the Freeside database. See the <a href="http://search.cpan.org/doc/TIMB/DBI/DBI.pm">DBI documentation</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">documentation for your DBD</a> for the exact syntax of a DBI data source.',
+ 'notes' => 'Real-time export of radcheck, radreply and usergroup tables to any SQL database for <a href="http://www.freeradius.org/">FreeRADIUS</a>, <a href="http://radius.innercite.com/">ICRADIUS</a> or <a href="http://www.open.com.au/radiator/">Radiator</a>. This export exports domains to RADIUS realms (see also sqlradius). An existing RADIUS database will be updated in realtime, but you can use <a href="../docs/man/bin/freeside-sqlradius-reset">freeside-sqlradius-reset</a> to delete the entire RADIUS database and repopulate the tables from the Freeside database. See the <a href="http://search.cpan.org/doc/TIMB/DBI/DBI.pm#connect">DBI documentation</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">documentation for your DBD</a> for the exact syntax of a DBI data source.<ul><li>Using FreeRADIUS 0.9.0 with the PostgreSQL backend, the db_postgresql.sql schema and postgresql.conf queries contain incompatible changes. This is fixed in 0.9.1. Only new installs with 0.9.0 and PostgreSQL are affected - upgrades and other database backends and versions are unaffected.<li>Using ICRADIUS, add a dummy "op" column to your database: <blockquote><code>ALTER&nbsp;TABLE&nbsp;radcheck&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'<br>ALTER&nbsp;TABLE&nbsp;radreply&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'<br>ALTER&nbsp;TABLE&nbsp;radgroupcheck&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'<br>ALTER&nbsp;TABLE&nbsp;radgroupreply&nbsp;ADD&nbsp;COLUMN&nbsp;op&nbsp;VARCHAR(2)&nbsp;NOT&nbsp;NULL&nbsp;DEFAULT&nbsp;\'==\'</code></blockquote><li>Using Radiator, see the <a href="http://www.open.com.au/radiator/faq.html#38">Radiator FAQ</a> for configuration information.</ul>',
},
'sqlmail' => {
@@ -958,6 +1008,19 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
'notes' => 'Real time export to <a href="http://inter7.com/vpopmail/">vpopmail</a> text files. <a href="http://search.cpan.org/search?dist=File-Rsync">File::Rsync</a> must be installed, and you will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a> to <b>vpopmail</b>@<i>export.host</i>.',
},
+ 'communigate_pro' => {
+ 'desc' => 'Real-time export to a CommuniGate Pro mail server',
+ 'options' => \%communigate_pro_options,
+ 'notes' => 'Real time export to a <a href="http://www.stalker.com/CommuniGatePro/">CommuniGate Pro</a> mail server. The <a href="http://www.stalker.com/CGPerl/">CommuniGate Pro Perl Interface</a> must be installed as CGP::CLI.',
+ },
+
+ 'communigate_pro_singledomain' => {
+ 'desc' => 'Real-time export to a CommuniGate Pro mail server, one domain only',
+ 'options' => \%communigate_pro_singledomain_options,
+ 'nodomain' => 'Y',
+ 'notes' => 'Real time export to a <a href="http://www.stalker.com/CommuniGatePro/">CommuniGate Pro</a> mail server. This is an unusual export to CommuniGate Pro that forces all accounts into a single domain. As CommuniGate Pro supports multiple domains, unless you have a specific reason for using this export, you probably want to use the communigate_pro export instead. The <a href="http://www.stalker.com/CGPerl/">CommuniGate Pro Perl Interface</a> must be installed as CGP::CLI.',
+ },
+
},
'svc_domain' => {
@@ -1001,7 +1064,7 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
'desc' => 'Real-time export to SQL-backed mail server',
'options' => \%sqlmail_options,
#'nodomain' => 'Y',
- 'notes' => 'Database schema can be made to work with Courier IMAP and Exim. Others could work but are untested. (...extended description from pc-intouch?...)',
+ 'notes' => 'Database schema can be made to work with Courier IMAP and Exim. Others could work but are untested. (...extended description from fire2wire?...)',
},
'forward_shellcommands' => {
@@ -1009,6 +1072,14 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
'options' => \%forward_shellcommands_options,
'notes' => 'Run remote commands via SSH, for forwards. You will need to <a href="../docs/ssh.html">setup SSH for unattended operation</a>.<BR><BR>Use these buttons for some useful presets:<UL><LI><INPUT TYPE="button" VALUE="text vpopmail maintenance" onClick=\'this.form.useradd.value = "[ -d /home/vpopmail/domains/$domain/$username ] && { echo \"$destination\" > /home/vpopmail/domains/$domain/$username/.qmail; chown vpopmail:vchkpw /home/vpopmail/domains/$domain/$username/.qmail; }"; this.form.userdel.value = "rm /home/vpopmail/domains/$domain/$username/.qmail"; this.form.usermod.value = "mv /home/vpopmail/domains/$old_domain/$old_username/.qmail /home/vpopmail/domains/$new_domain/$new_username; [ \"$old_destination\" != \"$new_destination\" ] && { echo \"$new_destination\" > /home/vpopmail/domains/$new_domain/$new_username/.qmail; chown vpopmail:vchkpw /home/vpopmail/domains/$new_domain/$new_username/.qmail; }";\'></UL>The following variables are available for interpolation (prefixed with <code>new_</code> or <code>old_</code> for replace operations): <UL><LI><code>$username</code><LI><code>$domain</code><LI><code>$destination</code> - forward destination<LI>All other fields in <a href="../docs/schema.html#svc_forward">svc_forward</a> are also available.</UL>',
},
+
+ 'postfix' => {
+ 'desc' => 'Real-time export to Postfix text files',
+ 'options' => \%postfix_options,
+ #'nodomain' => 'Y',
+ 'notes' => 'Batch export of Postfix aliases and virtual files. <a href="http://search.cpan.org/search?dist=File-Rsync">File::Rsync</a> must be installed. Run bin/postfix.export to export the files.',
+ },
+
},
'svc_www' => {
@@ -1032,6 +1103,10 @@ tie my %forward_shellcommands_options, 'Tie::IxHash',
'notes' => '',
},
},
+
+ 'svc_external' => {
+ },
+
);
=back
diff --git a/FS/FS/part_export/communigate_pro.pm b/FS/FS/part_export/communigate_pro.pm
new file mode 100644
index 000000000..557aad91d
--- /dev/null
+++ b/FS/FS/part_export/communigate_pro.pm
@@ -0,0 +1,144 @@
+package FS::part_export::communigate_pro;
+
+use vars qw(@ISA);
+use FS::part_export;
+use FS::queue;
+
+@ISA = qw(FS::part_export);
+
+sub rebless { shift; }
+
+sub export_username {
+ my($self, $svc_acct) = (shift, shift);
+ $svc_acct->email;
+}
+
+sub _export_insert {
+ my( $self, $svc_acct ) = (shift, shift);
+ my @options = ( $svc_acct->svcnum, 'CreateAccount',
+ 'accountName' => $self->export_username($svc_acct),
+ 'accountType' => $self->option('accountType'),
+ 'AccessModes' => $self->option('AccessModes'),
+ 'RealName' => $svc_acct->finger,
+ 'Password' => $svc_acct->_password,
+ );
+ push @options, 'MaxAccountSize' => $svc_acct->quota if $svc_acct->quota;
+ push @options, 'externalFlag' => $self->option('externalFlag')
+ if $self->option('externalFlag');
+
+ $self->communigate_pro_queue( @options );
+}
+
+sub _export_replace {
+ my( $self, $new, $old ) = (shift, shift, shift);
+ return "can't (yet) change username with CommuniGate Pro"
+ if $old->username ne $new->username;
+ return "can't (yet) change domain with CommuniGate Pro"
+ if $self->export_username($old) ne $self->export_username($new);
+ return "can't (yet) change GECOS with CommuniGate Pro"
+ if $old->finger ne $new->finger;
+ return "can't (yet) change quota with CommuniGate Pro"
+ if $old->quota ne $new->quota;
+ return '' unless $old->username ne $new->username
+ || $old->_password ne $new->_password
+ || $old->finger ne $new->finger
+ || $old->quota ne $new->quota;
+
+ return '' if '*SUSPENDED* '. $old->_password eq $new->_password;
+
+ #my $err_or_queue = $self->communigate_pro_queue( $new->svcnum,'RenameAccount',
+ # $old->email, $new->email );
+ #return $err_or_queue unless ref($err_or_queue);
+ #my $jobnum = $err_or_queue->jobnum;
+
+ $self->communigate_pro_queue( $new->svcnum, 'SetAccountPassword',
+ $self->export_username($new), $new->_password )
+ if $new->_password ne $old->_password;
+
+}
+
+sub _export_delete {
+ my( $self, $svc_acct ) = (shift, shift);
+ $self->communigate_pro_queue( $svc_acct->svcnum, 'DeleteAccount',
+ $self->export_username($svc_acct),
+ );
+}
+
+sub _export_suspend {
+ my( $self, $svc_acct ) = (shift, shift);
+ $self->communigate_pro_queue( $svc_acct->svcnum, 'UpdateAccountSettings',
+ 'accountName' => $self->export_username($svc_acct),
+ 'AccessModes' => 'Mail',
+ );
+}
+
+sub _export_unsuspend {
+ my( $self, $svc_acct ) = (shift, shift);
+ $self->communigate_pro_queue( $svc_acct->svcnum, 'UpdateAccountSettings',
+ 'accountName' => $self->export_username($svc_acct),
+ 'AccessModes' => $self->option('AccessModes'),
+ );
+}
+
+sub communigate_pro_queue {
+ my( $self, $svcnum, $method ) = (shift, shift, shift);
+ my @kludge_methods = qw(CreateAccount UpdateAccountSettings);
+ my $sub = 'communigate_pro_command';
+ $sub = $method if grep { $method eq $_ } @kludge_methods;
+ my $queue = new FS::queue {
+ 'svcnum' => $svcnum,
+ 'job' => "FS::part_export::communigate_pro::$sub",
+ };
+ $queue->insert(
+ $self->machine,
+ $self->option('port'),
+ $self->option('login'),
+ $self->option('password'),
+ $method,
+ @_,
+ );
+
+}
+
+sub CreateAccount {
+ my( $machine, $port, $login, $password, $method, %args ) = @_;
+ my $accountName = delete $args{'accountName'};
+ my $accountType = delete $args{'accountType'};
+ my $externalFlag = delete $args{'externalFlag'};
+ $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ];
+ my @args = ( accountName => $accountName,
+ accountType => $accountType,
+ settings => \%args,
+ );
+ #externalFlag => $externalFlag,
+ push @args, externalFlag => $externalFlag if $externalFlag;
+
+ communigate_pro_command( $machine, $port, $login, $password, $method, @args );
+
+}
+
+sub UpdateAccountSettings {
+ my( $machine, $port, $login, $password, $method, %args ) = @_;
+ my $accountName = delete $args{'accountName'};
+ $args{'AccessModes'} = [ split(' ', $args{'AccessModes'}) ];
+ @args = ( $accountName, \%args );
+ communigate_pro_command( $machine, $port, $login, $password, $method, @args );
+}
+
+sub communigate_pro_command { #subroutine, not method
+ my( $machine, $port, $login, $password, $method, @args ) = @_;
+
+ eval "use CGP::CLI";
+
+ my $cli = new CGP::CLI( {
+ 'PeerAddr' => $machine,
+ 'PeerPort' => $port,
+ 'login' => $login,
+ 'password' => $password,
+ } ) or die "Can't login to CGPro: $CGP::ERR_STRING\n";
+
+ $cli->$method(@args) or die "CGPro error: ". $cli->getErrMessage;
+
+ $cli->Logout or die "Can't logout of CGPro: $CGP::ERR_STRING\n";
+
+}
diff --git a/FS/FS/part_export/communigate_pro_singledomain.pm b/FS/FS/part_export/communigate_pro_singledomain.pm
new file mode 100644
index 000000000..11574af9b
--- /dev/null
+++ b/FS/FS/part_export/communigate_pro_singledomain.pm
@@ -0,0 +1,11 @@
+package FS::part_export::communigate_pro_singledomain;
+
+use vars qw(@ISA);
+use FS::part_export::communigate_pro;
+
+@ISA = qw(FS::part_export::communigate_pro);
+
+sub export_username {
+ my($self, $svc_acct) = (shift, shift);
+ $svc_acct->username. '@'. $self->option('domain');
+}
diff --git a/FS/FS/part_export/domain_shellcommands.pm b/FS/FS/part_export/domain_shellcommands.pm
index cf5603394..d295eece0 100644
--- a/FS/FS/part_export/domain_shellcommands.pm
+++ b/FS/FS/part_export/domain_shellcommands.pm
@@ -97,7 +97,7 @@ sub shellcommands_queue {
}
sub ssh_cmd { #subroutine, not method
- use Net::SSH '0.07';
+ use Net::SSH '0.08';
&Net::SSH::ssh_cmd( { @_ } );
}
diff --git a/FS/FS/part_export/forward_shellcommands.pm b/FS/FS/part_export/forward_shellcommands.pm
index f6fcb6062..5d3145715 100644
--- a/FS/FS/part_export/forward_shellcommands.pm
+++ b/FS/FS/part_export/forward_shellcommands.pm
@@ -97,7 +97,7 @@ sub shellcommands_queue {
}
sub ssh_cmd { #subroutine, not method
- use Net::SSH '0.07';
+ use Net::SSH '0.08';
&Net::SSH::ssh_cmd( { @_ } );
}
diff --git a/FS/FS/part_export/postfix.pm b/FS/FS/part_export/postfix.pm
new file mode 100644
index 000000000..6d5e449ca
--- /dev/null
+++ b/FS/FS/part_export/postfix.pm
@@ -0,0 +1,7 @@
+package FS::part_export::postfix;
+
+use vars qw(@ISA);
+use FS::part_export::null;
+
+@ISA = qw(FS::part_export::null);
+
diff --git a/FS/FS/part_export/router.pm b/FS/FS/part_export/router.pm
new file mode 100644
index 000000000..07b5b9edb
--- /dev/null
+++ b/FS/FS/part_export/router.pm
@@ -0,0 +1,166 @@
+package FS::part_export::router;
+
+=head1 FS::part_export::router
+
+This export connects to a router and transmits commands via telnet or SSH.
+It requires the following custom router fields:
+
+=over 4
+
+=item admin_address - IP address (or hostname) to connect
+
+=item admin_user - username for admin access
+
+=item admin_password - password for admin access
+
+=back
+
+The export itself needs the following options:
+
+=over 4
+
+=item insert, replace, delete - command strings (to be interpolated)
+
+=item Prompt - prompt string to expect from router after successful login
+
+=item Timeout - time to wait for prompt string
+
+=back
+
+(Prompt and Timeout are required only for telnet connections.)
+
+=cut
+
+use vars qw(@ISA @saltset);
+use String::ShellQuote;
+use FS::part_export;
+
+@ISA = qw(FS::part_export);
+
+@saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
+
+sub rebless { shift; }
+
+sub _export_insert {
+ my($self) = shift;
+ $self->_export_command('insert', @_);
+}
+
+sub _export_delete {
+ my($self) = shift;
+ $self->_export_command('delete', @_);
+}
+
+sub _export_suspend {
+ my($self) = shift;
+ $self->_export_command('suspend', @_);
+}
+
+sub _export_unsuspend {
+ my($self) = shift;
+ $self->_export_command('unsuspend', @_);
+}
+
+sub _export_command {
+ my ( $self, $action, $svc_broadband) = (shift, shift, shift);
+ my $command = $self->option($action);
+ return '' if $command =~ /^\s*$/;
+
+ no strict 'vars';
+ {
+ no strict 'refs';
+ ${$_} = $svc_broadband->getfield($_) foreach $svc_broadband->fields;
+ }
+ # fetch router info
+ my $router = $svc_broadband->addr_block->router;
+ my %r;
+ $r{$_} = $router->getfield($_) foreach $router->virtual_fields;
+ #warn qq("$command");
+ #warn eval(qq("$command"));
+
+ warn "admin_address: '$r{admin_address}'";
+
+ if ($r{admin_address} ne '') {
+ $self->router_queue( $svc_broadband->svcnum, $self->option('protocol'),
+ user => $r{admin_user},
+ password => $r{admin_password},
+ host => $r{admin_address},
+ Timeout => $self->option('Timeout'),
+ Prompt => $self->option('Prompt'),
+ command => eval(qq("$command")),
+ );
+ } else {
+ return '';
+ }
+}
+
+sub _export_replace {
+
+ # We don't handle the case of a svc_broadband moving between routers.
+ # If you want to do that, reprovision the service.
+
+ my($self, $new, $old ) = (shift, shift, shift);
+ my $command = $self->option('replace');
+ no strict 'vars';
+ {
+ no strict 'refs';
+ ${"old_$_"} = $old->getfield($_) foreach $old->fields;
+ ${"new_$_"} = $new->getfield($_) foreach $new->fields;
+ }
+
+ my $router = $new->addr_block->router;
+ my %r;
+ $r{$_} = $router->getfield($_) foreach $router->virtual_fields;
+
+ if ($r{admin_address} ne '') {
+ $self->router_queue( $new->svcnum, $self->option('protocol'),
+ user => $r{admin_user},
+ password => $r{admin_password},
+ host => $r{admin_address},
+ Timeout => $self->option('Timeout'),
+ Prompt => $self->option('Prompt'),
+ command => eval(qq("$command")),
+ );
+ } else {
+ return '';
+ }
+}
+
+#a good idea to queue anything that could fail or take any time
+sub router_queue {
+ #warn join ':', @_;
+ my( $self, $svcnum, $protocol ) = (shift, shift, shift);
+ my $queue = new FS::queue {
+ 'svcnum' => $svcnum,
+ };
+ $queue->job ("FS::part_export::router::".$protocol."_cmd");
+ $queue->insert( @_ );
+}
+
+sub ssh_cmd { #subroutine, not method
+ use Net::SSH '0.08';
+ &Net::SSH::ssh_cmd( { @_ } );
+}
+
+sub telnet_cmd {
+ use Net::Telnet;
+
+ warn join(', ', @_);
+
+ my %arg = @_;
+
+ my $t = new Net::Telnet (Timeout => $arg{Timeout},
+ Prompt => $arg{Prompt});
+ $t->open($arg{host});
+ $t->login($arg{user}, $arg{password});
+ my @error = $t->cmd($arg{command});
+ die @error if (grep /^ERROR/, @error);
+}
+
+#sub router_insert { #subroutine, not method
+#}
+#sub router_replace { #subroutine, not method
+#}
+#sub router_delete { #subroutine, not method
+#}
+
diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm
index edc944009..db2e7aaf9 100644
--- a/FS/FS/part_export/shellcommands.pm
+++ b/FS/FS/part_export/shellcommands.pm
@@ -40,6 +40,13 @@ sub _export_command {
{
no strict 'refs';
${$_} = $svc_acct->getfield($_) foreach $svc_acct->fields;
+
+ my $count = 1;
+ foreach my $acct_snarf ( $svc_acct->acct_snarf ) {
+ ${"snarf_$_$count"} = shell_quote( $acct_snarf->get($_) )
+ foreach qw( machine username _password );
+ $count++;
+ }
}
my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
@@ -90,6 +97,12 @@ sub _export_replace {
if ( $old_domain ne $new_domain ) {
$error ||= "can't change domain";
}
+ if ( $old_uid != $new_uid ) {
+ $error ||= "can't change uid";
+ }
+ if ( $old_dir ne $new_dir ) {
+ $error ||= "can't change dir";
+ }
return $error. ' ('. $self->exporttype. ' to '. $self->machine. ')'
if $error;
}
@@ -112,7 +125,7 @@ sub shellcommands_queue {
}
sub ssh_cmd { #subroutine, not method
- use Net::SSH '0.07';
+ use Net::SSH '0.08';
&Net::SSH::ssh_cmd( { @_ } );
}
diff --git a/FS/FS/part_export/www_shellcommands.pm b/FS/FS/part_export/www_shellcommands.pm
index 20658c7a2..3e0087446 100644
--- a/FS/FS/part_export/www_shellcommands.pm
+++ b/FS/FS/part_export/www_shellcommands.pm
@@ -96,7 +96,7 @@ sub shellcommands_queue {
}
sub ssh_cmd { #subroutine, not method
- use Net::SSH '0.07';
+ use Net::SSH '0.08';
&Net::SSH::ssh_cmd( { @_ } );
}
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm
index 12ee804ff..dcce66b38 100644
--- a/FS/FS/part_pkg.pm
+++ b/FS/FS/part_pkg.pm
@@ -2,7 +2,7 @@ package FS::part_pkg;
use strict;
use vars qw( @ISA );
-use FS::Record qw( qsearch dbh );
+use FS::Record qw( qsearch dbh dbdef );
use FS::pkg_svc;
use FS::agent_type;
use FS::type_pkgs;
@@ -229,11 +229,19 @@ sub check {
}
+ if ( $self->dbdef_table->column('freq')->type =~ /(int)/i ) {
+ my $error = $self->ut_number('freq');
+ return $error if $error;
+ } else {
+ $self->freq =~ /^(\d+[dw]?)$/
+ or return "Illegal or empty freq: ". $self->freq;
+ $self->freq($1);
+ }
+
$self->ut_numbern('pkgpart')
|| $self->ut_text('pkg')
|| $self->ut_text('comment')
|| $self->ut_anything('setup')
- || $self->ut_number('freq')
|| $self->ut_anything('recur')
|| $self->ut_alphan('plan')
|| $self->ut_anything('plandata')
@@ -259,20 +267,24 @@ sub pkg_svc {
=item svcpart [ SVCDB ]
-Returns the svcpart of a single service definition (see L<FS::part_svc>)
+Returns the svcpart of the primary service definition (see L<FS::part_svc>)
associated with this billing item definition (see L<FS::pkg_svc>). Returns
-false if there not exactly one service definition with quantity 1, or if
-SVCDB is specified and does not match the svcdb of the service definition,
+false if there not a primary service definition or exactly one service
+definition with quantity 1, or if SVCDB is specified and does not match the
+svcdb of the service definition,
=cut
sub svcpart {
my $self = shift;
my $svcdb = scalar(@_) ? shift : '';
- my @pkg_svc = grep {
- $_->quantity == 1
- && ( $svcdb eq $_->part_svc->svcdb || !$svcdb )
- } $self->pkg_svc;
+ my @svcdb_pkg_svc =
+ grep { ( $svcdb eq $_->part_svc->svcdb || !$svcdb ) } $self->pkg_svc;
+ my @pkg_svc = ();
+ @pkg_svc = grep { $_->primary_svc =~ /^Y/i } @svcdb_pkg_svc
+ if dbdef->table('pkg_svc')->column('primary_svc');
+ @pkg_svc = grep {$_->quantity == 1 } @svcdb_pkg_svc
+ unless @pkg_svc;
return '' if scalar(@pkg_svc) != 1;
$pkg_svc[0]->svcpart;
}
diff --git a/FS/FS/part_referral.pm b/FS/FS/part_referral.pm
index f30ddad01..c0858c0ed 100644
--- a/FS/FS/part_referral.pm
+++ b/FS/FS/part_referral.pm
@@ -38,6 +38,8 @@ The following fields are currently supported:
=item referral - Text name of this advertising source
+=item disabled - Disabled flag, empty or 'Y'
+
=back
=head1 NOTE
@@ -91,10 +93,17 @@ replace methods.
sub check {
my $self = shift;
- $self->ut_numbern('refnum')
+ my $error = $self->ut_numbern('refnum')
|| $self->ut_text('referral')
- || $self->SUPER::check
;
+ return $error if $error;
+
+ if ( $self->dbdef_table->column('disabled') ) {
+ $error = $self->ut_enum('disabled', [ '', 'Y' ] );
+ return $error if $error;
+ }
+
+ $self->SUPER::check;
}
=back
diff --git a/FS/FS/pkg_svc.pm b/FS/FS/pkg_svc.pm
index 2ac1a558c..ea52176cb 100644
--- a/FS/FS/pkg_svc.pm
+++ b/FS/FS/pkg_svc.pm
@@ -46,6 +46,8 @@ FS::Record. The following fields are currently supported:
=item quantity - Quantity of this service definition that this billing item
definition includes
+=item primary_svc - primary flag, empty or 'Y'
+
=back
=head1 METHODS
@@ -108,6 +110,11 @@ sub check {
return "Unknown pkgpart!" unless $self->part_pkg;
return "Unknown svcpart!" unless $self->part_svc;
+ if ( $self->dbdef_table->column('primary_svc') ) {
+ $error = $self->ut_enum('primary_svc', [ '', 'Y' ] );
+ return $error if $error;
+ }
+
$self->SUPER::check;
}
@@ -135,10 +142,6 @@ sub part_svc {
=back
-=head1 VERSION
-
-$Id: pkg_svc.pm,v 1.4 2003-08-05 00:20:45 khoff Exp $
-
=head1 BUGS
=head1 SEE ALSO
diff --git a/FS/FS/raddb.pm b/FS/FS/raddb.pm
index a35a757f5..efeb739bb 100644
--- a/FS/FS/raddb.pm
+++ b/FS/FS/raddb.pm
@@ -4,1099 +4,1592 @@ use vars qw(%attrib);
%attrib = (
'usr_at_zip_output_filter' => 'USR-AT-Zip-Output-Filter',
'ms_filter' => 'MS-Filter',
+ 'annex_compression_protoc' => 'Annex-Compression-Protocol',
+ 'xedia_ssh_privileges' => 'Xedia-SSH-Privileges',
'usr_blocks_received' => 'USR-Blocks-Received',
'shiva_called_number' => 'Shiva-Called-Number',
'annex_filter' => 'Annex-Filter',
'usr_channel_expansion' => 'USR-Channel-Expansion',
+ 'erx_tunnel_tos' => 'ERX-Tunnel-Tos',
'session_timeout' => 'Session-Timeout',
- 'usr_simplified_mnp_level' => 'USR-Simplified-MNP-Levels',
'ascend_route_ipx' => 'Ascend-Route-IPX',
- 'annex_user_server_locati' => 'Annex-User-Server-Location',
+ 'annex_error_correction_p' => 'Annex-Error-Correction-Prot',
'acc_callback_mode' => 'Acc-Callback-Mode',
'usr_filter_zones' => 'USR-Filter-Zones',
+ 'erx_input_gigapkts' => 'ERX-Input-Gigapkts',
'ascend_session_svr_key' => 'Ascend-Session-Svr-Key',
- 'le_nat_tcp_session_timeo' => 'LE-NAT-TCP-Session-Timeout',
+ 'bind_l2tp_tunnel_namf' => 'Bind_L2TP_Tunnel_Name',
+ 'ascend_dsl_cir_recv_limi' => 'Ascend-Dsl-CIR-Recv-Limit',
+ 'altiga_secondary_wins_g' => 'Altiga-Secondary-WINS-G',
'ascend_ts_idle_limit' => 'Ascend-TS-Idle-Limit',
'usr_port_tap_priority' => 'USR-Port-Tap-Priority',
+ 'cvpn3000_ipsec_client_fw' => 'CVPN3000-IPSec-Client-Fw-Filter-Name',
+ 'ascend_private_route_req' => 'Ascend-Private-Route-Required',
'ascend_private_route' => 'Ascend-Private-Route',
'prompt' => 'Prompt',
'acct_link_count' => 'Acct-Link-Count',
+ 'bind_auth_service_grq' => 'Bind_Auth_Service_Grp',
+ 'itk_tunnel_ip' => 'ITK-Tunnel-IP',
'login_lat_node' => 'Login-LAT-Node',
'usr_mbi_ct_pri_card_slot' => 'USR-Mbi_Ct_PRI_Card_Slot',
+ 'lac_real_poru' => 'LAC_Real_Port',
'erx_ingress_statistics' => 'ERX-Ingress-Statistics',
+ 'digest_nonce' => 'Digest-Nonce',
'annex_system_disc_reason' => 'Annex-System-Disc-Reason',
+ 'pool_name' => 'Pool-Name',
+ 'altiga_use_client_addres' => 'Altiga-Use-Client-Address-G/U',
+ 'police_bursu' => 'Police_Burst',
'usr_call_arrival_time' => 'USR-Call-Arrival-Time',
'ascend_disconnect_cause' => 'Ascend-Disconnect-Cause',
'ascend_user_acct_time' => 'Ascend-User-Acct-Time',
- 'ascend_appletalk_peer_mo' => 'Ascend-Appletalk-Peer-Mode',
'chap_challenge' => 'CHAP-Challenge',
'ascend_mpp_idle_percent' => 'Ascend-MPP-Idle-Percent',
'ascend_user_acct_port' => 'Ascend-User-Acct-Port',
+ 'ldap_group' => 'Ldap-Group',
'ascend_numbering_plan_id' => 'Ascend-Numbering-Plan-ID',
- 'ascend_access_intercept_' => 'Ascend-Access-Intercept-LEA',
- 'pvc_encapsulation_type' => 'PVC_Encapsulation_Type',
+ 'usr_last_number_dialed_o' => 'USR-Last-Number-Dialed-Out',
+ 'pvc_encapsulation_type' => 'PVC-Encapsulation-Type',
'ascend_bir_bridge_group' => 'Ascend-BIR-Bridge-Group',
'ascend_atm_group' => 'Ascend-ATM-Group',
'ascend_fr_svc_addr' => 'Ascend-FR-SVC-Addr',
'x_ascend_send_auth' => 'X-Ascend-Send-Auth',
'le_ip_pool' => 'LE-IP-Pool',
- 'annex_addr_resolution_se' => 'Annex-Addr-Resolution-Servers',
- 'usr_last_callers_number_' => 'USR-Last-Callers-Number-ANI',
+ 'post_proxy_type' => 'Post-Proxy-Type',
+ 'wispr_session_terminate_' => 'WISPr-Session-Terminate-Time',
+ 'bintec_pppextiftable' => 'BinTec-pppExtIfTable',
+ 'nomadix_subnet' => 'Nomadix-Subnet',
'login_port' => 'Login-Port',
'ms_chap2_response' => 'MS-CHAP2-Response',
- 'annex_secondary_dns_serv' => 'Annex-Secondary-DNS-Server',
'ascend_ipsec_profile' => 'Ascend-IPSEC-Profile',
+ 'usr_compression_algorith' => 'USR-Compression-Algorithm',
'usr_accm_type' => 'USR-ACCM-Type',
'simultaneous_use' => 'Simultaneous-Use',
+ 'cisco_account_info' => 'Cisco-Account-Info',
'framed_protocol' => 'Framed-Protocol',
+ 'erx_tunnel_maximum_sessi' => 'ERX-Tunnel-Maximum-Sessions',
+ 'redcreek_tunneled_wins_t' => 'RedCreek-Tunneled-WINS-Server2',
'ascend_recv_name' => 'Ascend-Recv-Name',
'usr_call_connecting_time' => 'USR-Call-Connecting-Time',
- 'tunnel_remote_name' => 'Tunnel_Remote_Name',
+ 'quintum_h323_gw_id' => 'Quintum-h323-gw-id',
+ 'acct_dyn_ac_ent' => 'Acct-Dyn-Ac-Ent',
+ 'tunnel_remote_name' => 'Tunnel-Remote-Name',
+ 'annex_ppp_trace_level' => 'Annex-PPP-Trace-Level',
+ 'cisco_call_type' => 'Cisco-Call-Type',
+ 'cisco_fax_recipient_coun' => 'Cisco-Fax-Recipient-Count',
+ 'altiga_ipsec_authenticat' => 'Altiga-IPSec-Authentication-G',
+ 'wispr_location_id' => 'WISPr-Location-ID',
+ 'itk_start_delay' => 'ITK-Start-Delay',
+ 'ascend_pre_output_packet' => 'Ascend-Pre-Output-Packets',
+ 'usr_rmmie_firmware_versi' => 'USR-RMMIE-Firmware-Version',
'usr_vts_session_key' => 'USR-VTS-Session-Key',
'ascend_fr_dce_n393' => 'Ascend-FR-DCE-N393',
'login_host' => 'Login-Host',
'usr_reply_script3' => 'USR-Reply-Script3',
+ 'cvpn3000_ipsec_split_tuo' => 'CVPN3000-IPSec-Split-Tunneling-Policy',
'ascend_pppoe_enable' => 'Ascend-PPPoE-Enable',
'annex_primary_dns_server' => 'Annex-Primary-DNS-Server',
'x_ascend_bridge_address' => 'X-Ascend-Bridge-Address',
'usr_number_of_link_naks' => 'USR-Number-of-Link-NAKs',
+ 'altiga_priority_on_sep_g' => 'Altiga-Priority-on-SEP-G/U',
'annex_cli_command' => 'Annex-CLI-Command',
'usr_pw_framed_routing_v2' => 'USR-PW_Framed_Routing_V2',
- 'usr_tunnel_switch_endpoi' => 'USR-Tunnel-Switch-Endpoint',
+ 'session_error_codf' => 'Session_Error_Code',
+ 'annex_user_server_locati' => 'Annex-User-Server-Location',
+ 'cisco_fax_mdn_address' => 'Cisco-Fax-Mdn-Address',
+ 'ascend_calling_subaddres' => 'Ascend-Calling-Subaddress',
'ascend_call_by_call' => 'Ascend-Call-By-Call',
'ascend_first_dest' => 'Ascend-First-Dest',
- 'usr_appletalk_network_ra' => 'USR-Appletalk-Network-Range',
'annex_tunnel_authen_type' => 'Annex-Tunnel-Authen-Type',
+ 'acct_type' => 'Acct-Type',
'sql_user_name' => 'SQL-User-Name',
'erx_secondary_dns' => 'ERX-Secondary-Dns',
+ 'bridge_grouq' => 'Bridge_Group',
'h323_return_code' => 'h323-return-code',
'annex_host_allow' => 'Annex-Host-Allow',
+ 'cvx_modem_end_recv_line_' => 'CVX-Modem-End-Recv-Line-Lvl',
+ 'sip_method' => 'Sip-Method',
'x_ascend_require_auth' => 'X-Ascend-Require-Auth',
+ 'cvpn3000_sep_card_assign' => 'CVPN3000-SEP-Card-Assignment',
'le_ipsec_deny_action' => 'LE-IPSec-Deny-Action',
'annex_edo' => 'Annex-EDO',
'acct_delay_time' => 'Acct-Delay-Time',
- 'ascend_call_block_durati' => 'Ascend-Call-Block-Duration',
'login_tcp_port' => 'Login-TCP-Port',
'ascend_temporary_rtes' => 'Ascend-Temporary-Rtes',
+ 'versanet_termination_cau' => 'Versanet-Termination-Cause',
'ascend_dialed_number' => 'Ascend-Dialed-Number',
- 'x_ascend_dec_channel_cou' => 'X-Ascend-Dec-Channel-Count',
+ 'cvpn3000_ipsec_authentic' => 'CVPN3000-IPSec-Authentication',
'ascend_fr_dlci' => 'Ascend-FR-DLCI',
'annex_modem_disc_reason' => 'Annex-Modem-Disc-Reason',
'x_ascend_receive_secret' => 'X-Ascend-Receive-Secret',
+ 'usr_ospf_addressless_ind' => 'USR-OSPF-Addressless-Index',
+ 'usr_ip_default_route_opt' => 'USR-IP-Default-Route-Option',
'char_noecho' => 'Char-Noecho',
+ 'redcreek_tunneled_search' => 'RedCreek-Tunneled-Search-List',
'ascend_pri_number_type' => 'Ascend-PRI-Number-Type',
- 'ascend_dsl_upstream_limi' => 'Ascend-Dsl-Upstream-Limit',
+ 'aat_ip_tos_apply_to' => 'AAT-IP-TOS-Apply-To',
'x_ascend_modem_shelfno' => 'X-Ascend-Modem-ShelfNo',
'prefix' => 'Prefix',
'usr_rad_dvmrp_metric' => 'USR-Rad-Dvmrp-Metric',
+ 'x_ascend_call_attempt_li' => 'X-Ascend-Call-Attempt-Limit',
'usr_ip_saa_filter' => 'USR-IP-SAA-Filter',
- 'ms_link_utilization_thre' => 'MS-Link-Utilization-Threshold',
+ 'itk_prompt' => 'ITK-Prompt',
+ 'ascend_port_redir_protoc' => 'Ascend-Port-Redir-Protocol',
+ 'cvx_modem_tx_packets' => 'CVX-Modem-Tx-Packets',
+ 'usr_tunnel_switch_endpoi' => 'USR-Tunnel-Switch-Endpoint',
'ascend_home_network_name' => 'Ascend-Home-Network-Name',
'acc_customer_id' => 'Acc-Customer-Id',
'message_authenticator' => 'Message-Authenticator',
- 'ascend_secondary_home_ag' => 'Ascend-Secondary-Home-Agent',
- 'x_ascend_pre_output_octe' => 'X-Ascend-Pre-Output-Octets',
+ 'cisco_fax_coverpage_flag' => 'Cisco-Fax-Coverpage-Flag',
'usr_multicast_forwarding' => 'USR-Multicast-Forwarding',
+ 'cvpn3000_allow_network_e' => 'CVPN3000-Allow-Network-Extension-Mode',
'ascend_call_direction' => 'Ascend-Call-Direction',
'acc_connect_rx_speed' => 'Acc-Connect-Rx-Speed',
'ascend_force_56' => 'Ascend-Force-56',
+ 'st_service_domain' => 'ST-Service-Domain',
'usr_harc_disconnect_code' => 'USR-HARC-Disconnect-Code',
'shasta_service_profile' => 'Shasta-Service-Profile',
'cisco_maximum_time' => 'Cisco-Maximum-Time',
'usr_tunnel_auth_hostname' => 'USR-Tunnel-Auth-Hostname',
- 'ascend_client_assign_win' => 'Ascend-Client-Assign-WINS',
- 'acc_modem_modulation_typ' => 'Acc-Modem-Modulation-Type',
'acc_ip_gateway_pri' => 'Acc-Ip-Gateway-Pri',
'ascend_bridge_address' => 'Ascend-Bridge-Address',
+ 'altiga_pptp_min_authenti' => 'Altiga-PPTP-Min-Authentication-G/U',
+ 'ns_secondary_wins' => 'NS-Secondary-WINS',
+ 'cbbsm_bandwidth' => 'CBBSM-Bandwidth',
'x_ascend_fr_link_mgt' => 'X-Ascend-FR-Link-Mgt',
+ 'altiga_ipsec_banner_g' => 'Altiga-IPSec-Banner-G',
'ascend_handle_ipx' => 'Ascend-Handle-IPX',
'ascend_x25_pad_alias_2' => 'Ascend-X25-Pad-Alias-2',
+ 'st_policy_name' => 'ST-Policy-Name',
'ascend_group' => 'Ascend-Group',
'ascend_dsl_rate_type' => 'Ascend-Dsl-Rate-Type',
+ 'tunnel_contexu' => 'Tunnel_Context',
'ascend_require_auth' => 'Ascend-Require-Auth',
+ 'cvx_modem_local_retrains' => 'CVX-Modem-Local-Retrains',
+ 'cvpn5000_echo' => 'CVPN5000-Echo',
+ 'cvx_secondary_dns' => 'CVX-Secondary-DNS',
'x_ascend_billing_number' => 'X-Ascend-Billing-Number',
'usr_orig_nas_type' => 'USR-Orig-NAS-Type',
'ascend_remote_fw' => 'Ascend-Remote-FW',
'acct_output_packets' => 'Acct-Output-Packets',
'lm_password' => 'LM-Password',
- 'tunnel_window' => 'Tunnel_Window',
- 'x_ascend_link_compressio' => 'X-Ascend-Link-Compression',
- 'x_ascend_base_channel_co' => 'X-Ascend-Base-Channel-Count',
+ 'tunnel_window' => 'Tunnel-Window',
'cisco_avpair' => 'Cisco-AVPair',
+ 'st_service_name' => 'ST-Service-Name',
'shiva_event_flags' => 'Shiva-Event-Flags',
- 'usr_number_of_rings_limi' => 'USR-Number-of-Rings-Limit',
+ 'annex_retrain_requests_s' => 'Annex-Retrain-Requests-Sent',
'ascend_ts_idle_mode' => 'Ascend-TS-Idle-Mode',
- 'ascend_bi_directional_au' => 'Ascend-Bi-Directional-Auth',
+ 'usr_ip_rip_simple_auth_p' => 'USR-IP-RIP-Simple-Auth-Password',
+ 'tunnel_deadtimf' => 'Tunnel_Deadtime',
'state' => 'State',
'usr_keypress_timeout' => 'USR-Keypress-Timeout',
'usr_pw_vpn_neighbor' => 'USR-PW_VPN_Neighbor',
+ 'erx_pppoe_description' => 'ERX-Pppoe-Description',
'ldap_userdn' => 'Ldap-UserDn',
'x_ascend_fr_n391' => 'X-Ascend-FR-N391',
- 'ascend_tunneling_protoco' => 'Ascend-Tunneling-Protocol',
+ 'ascend_calling_id_presen' => 'Ascend-Calling-Id-Presentatn',
+ 'erx_local_loopback_inter' => 'ERX-Local-Loopback-Interface',
'x_ascend_fr_direct' => 'X-Ascend-FR-Direct',
'nas_ip_address' => 'NAS-IP-Address',
'usr_call_end_time' => 'USR-Call-End-Time',
- 'tunnel_algorithm' => 'Tunnel_Algorithm',
+ 'acct_mcast_out_packett' => 'Acct_Mcast_Out_Packets',
+ 'tunnel_algorithm' => 'Tunnel-Algorithm',
'usr_vpn_encrypter' => 'USR-VPN-Encrypter',
+ 'tunnel_grouq' => 'Tunnel_Group',
'ascend_atm_connect_group' => 'Ascend-ATM-Connect-Group',
'x_ascend_ft1_caller' => 'X-Ascend-FT1-Caller',
+ 'usr_dnis_reauthenticatio' => 'USR-DNIS-ReAuthentication',
'login_callback_number' => 'Login-Callback-Number',
'usr_ip_rip_input_filter' => 'USR-IP-RIP-Input-Filter',
- 'usr_rmmie_last_update_ev' => 'USR-RMMIE-Last-Update-Event',
+ 'usr_rmmie_rcv_pwrlvl_330' => 'USR-RMMIE-Rcv-PwrLvl-3300Hz',
'h323_disconnect_cause' => 'h323-disconnect-cause',
'x_ascend_handle_ipx' => 'X-Ascend-Handle-IPX',
'usr_igmp_version' => 'USR-IGMP-Version',
'usr_imsi' => 'USR-IMSI',
'group_name' => 'Group-Name',
'usr_nas_type' => 'USR-NAS-Type',
+ 'context_namf' => 'Context-Name',
'ascend_ip_tos' => 'Ascend-IP-TOS',
'x_ascend_token_immediate' => 'X-Ascend-Token-Immediate',
- 'ascend_private_route_tab' => 'Ascend-Private-Route-Table-ID',
+ 'tunnel_session_auth_serw' => 'Tunnel_Session_Auth_Service_Grp',
'ms_chap2_cpw' => 'MS-CHAP2-CPW',
- 'tunnel_session_auth_ctx' => 'Tunnel_Session_Auth_Ctx',
+ 'tunnel_session_auth_ctx' => 'Tunnel-Session-Auth-Ctx',
'usr_mobile_numbytes_rxed' => 'USR-Mobile-NumBytes-Rxed',
'usr_mbi_ct_tdm_time_slot' => 'USR-Mbi_Ct_TDM_Time_Slot',
'ascend_x25_nui' => 'Ascend-X25-Nui',
'x_ascend_first_dest' => 'X-Ascend-First-Dest',
- 'x_ascend_num_in_multilin' => 'X-Ascend-Num-In-Multilink',
'usr_send_password' => 'USR-Send-Password',
+ 'x_ascend_fr_direct_profi' => 'X-Ascend-FR-Direct-Profile',
'x_ascend_fr_t391' => 'X-Ascend-FR-T391',
+ 'altiga_ipsec_sec_associa' => 'Altiga-IPSec-Sec-Association-G/U',
+ 'ip_address_pool_namf' => 'Ip_Address_Pool_Name',
'acct_input_octets' => 'Acct-Input-Octets',
- 'bridge_group' => 'Bridge_Group',
+ 'cvx_modem_begin_modulati' => 'CVX-Modem-Begin-Modulation',
+ 'wispr_session_terminatea' => 'WISPr-Session-Terminate-End-Of-Day',
+ 'cvpn3000_use_client_addr' => 'CVPN3000-Use-Client-Address',
+ 'bridge_group' => 'Bridge-Group',
'annex_sec_profile_index' => 'Annex-Sec-Profile-Index',
'acc_dns_server_pri' => 'Acc-Dns-Server-Pri',
'ms_acct_auth_type' => 'MS-Acct-Auth-Type',
+ 'x_ascend_maximum_call_du' => 'X-Ascend-Maximum-Call-Duration',
'tunnel_password' => 'Tunnel-Password',
+ 'framed_ipv6_prefix' => 'Framed-IPv6-Prefix',
'usr_reply_script5' => 'USR-Reply-Script5',
'shiva_links_in_bundle' => 'Shiva-Links-In-Bundle',
'ascend_fr_profile_name' => 'Ascend-FR-Profile-Name',
'ascend_mtu' => 'Ascend-MTU',
+ 'nokia_charging_id' => 'Nokia-Charging-Id',
+ 'cvpn3000_ms_client_subne' => 'CVPN3000-MS-Client-Subnet-Mask',
+ 'cvpn3000_ipsec_sec_assoc' => 'CVPN3000-IPSec-Sec-Association',
'cisco_ppp_async_map' => 'Cisco-PPP-Async-Map',
+ 'cvpn3000_user_auth_servf' => 'CVPN3000-User-Auth-Server-Port',
'cisco_num_in_multilink' => 'Cisco-Num-In-Multilink',
+ 'wispr_logoff_url' => 'WISPr-Logoff-URL',
'usr_mobile_ip_address' => 'USR-Mobile-IP-Address',
+ 'usr_final_tx_link_data_r' => 'USR-Final-Tx-Link-Data-Rate',
+ 'itk_ppp_compression_prot' => 'ITK-PPP-Compression-Prot',
'ascend_bridge' => 'Ascend-Bridge',
'x_ascend_presession_time' => 'X-Ascend-PreSession-Time',
- 'tunnel_cmd_timeout' => 'Tunnel_Cmd_Timeout',
+ 'aat_client_primary_dns' => 'AAT-Client-Primary-DNS',
+ 'cvpn3000_strip_realm' => 'CVPN3000-Strip-Realm',
+ 'tunnel_cmd_timeout' => 'Tunnel-Cmd-Timeout',
'ascend_multicast_client' => 'Ascend-Multicast-Client',
+ 'cvx_modem_remote_rate_ne' => 'CVX-Modem-Remote-Rate-Negs',
'tunnel_private_group_id' => 'Tunnel-Private-Group-Id',
'usr_rmmie_rcv_tot_pwrlvl' => 'USR-RMMIE-Rcv-Tot-PwrLvl',
'calling_station_id' => 'Calling-Station-Id',
- 'tunnel_rate_limit_burst' => 'Tunnel_Rate_Limit_Burst',
+ 'tunnel_rate_limit_burst' => 'Tunnel-Rate-Limit-Burst',
'usr_device_connected_to' => 'USR-Device-Connected-To',
+ 'aat_source_ip_check' => 'AAT-Source-IP-Check',
'login_lat_service' => 'Login-LAT-Service',
- 'x_ascend_home_network_na' => 'X-Ascend-Home-Network-Name',
'ascend_h323_fegw_address' => 'Ascend-H323-Fegw-Address',
'usr_called_party_number' => 'USR-Called-Party-Number',
+ 'bintec_ipnatpresettable' => 'BinTec-ipNatPresetTable',
'ascend_remove_seconds' => 'Ascend-Remove-Seconds',
'shiva_user_attributes' => 'Shiva-User-Attributes',
+ 'cisco_fax_dsn_flag' => 'Cisco-Fax-Dsn-Flag',
'x_ascend_route_ipx' => 'X-Ascend-Route-IPX',
'acc_route_policy' => 'Acc-Route-Policy',
+ 'bind_l2tp_flow_controm' => 'Bind_L2TP_Flow_Control',
+ 'erx_qos_profile_name' => 'ERX-Qos-Profile-Name',
'x_ascend_client_gateway' => 'X-Ascend-Client-Gateway',
- 'ms_mppe_encryption_polic' => 'MS-MPPE-Encryption-Policy',
+ 'pre_proxy_type' => 'Pre-Proxy-Type',
+ 'smb_account_ctrl_text' => 'SMB-Account-CTRL-TEXT',
'x_ascend_data_filter' => 'X-Ascend-Data-Filter',
+ 'usr_rmmie_last_update_ti' => 'USR-RMMIE-Last-Update-Time',
'ascend_atm_direct' => 'Ascend-ATM-Direct',
'ascend_session_type' => 'Ascend-Session-Type',
'x_ascend_fr_linkup' => 'X-Ascend-FR-LinkUp',
'ascend_metric' => 'Ascend-Metric',
+ 'x_ascend_assign_ip_clien' => 'X-Ascend-Assign-IP-Client',
'usr_speed_of_connection' => 'USR-Speed-Of-Connection',
+ 'cvpn3000_require_hw_clie' => 'CVPN3000-Require-HW-Client-Auth',
+ 'session_type' => 'Session-Type',
+ 'acct_input_octets_65' => 'Acct_Input_Octets_64',
'le_nat_outsource_outmap' => 'LE-NAT-Outsource-Outmap',
- 'pppoe_url' => 'PPPOE_URL',
- 'acct_mcast_out_octets' => 'Acct_Mcast_Out_Octets',
+ 'cvx_modem_local_rate_neg' => 'CVX-Modem-Local-Rate-Negs',
+ 'mcast_sene' => 'Mcast_Send',
+ 'pppoe_url' => 'PPPOE-URL',
+ 'erx_service_bundle' => 'ERX-Service-Bundle',
+ 'altiga_secondary_dns_g' => 'Altiga-Secondary-DNS-G',
+ 'bg_trans_bpdv' => 'BG_Trans_BPDU',
+ 'cvx_data_filter' => 'CVX-Data-Filter',
+ 'acct_mcast_out_octets' => 'Acct-Mcast-Out-Octets',
'ascend_callback' => 'Ascend-Callback',
'tunnel_client_auth_id' => 'Tunnel-Client-Auth-Id',
'acct_unique_session_id' => 'Acct-Unique-Session-Id',
'usr_port_tap_format' => 'USR-Port-Tap-Format',
'ascend_ckt_type' => 'Ascend-Ckt-Type',
'ascend_ppp_async_map' => 'Ascend-PPP-Async-Map',
+ 'usr_rmmie_rcv_pwrlvl_375' => 'USR-RMMIE-Rcv-PwrLvl-3750Hz',
'usr_acct_reason_code' => 'USR-Acct-Reason-Code',
'ascend_filter' => 'Ascend-Filter',
'h323_redirect_number' => 'h323-redirect-number',
'port_limit' => 'Port-Limit',
- 'x_ascend_shared_profile_' => 'X-Ascend-Shared-Profile-Enable',
- 'tunnel_police_rate' => 'Tunnel_Police_Rate',
- 'ascend_calling_id_screen' => 'Ascend-Calling-Id-Screening',
+ 'rewrite_rule' => 'Rewrite-Rule',
+ 'tunnel_police_rate' => 'Tunnel-Police-Rate',
'usr_multicast_proxy' => 'USR-Multicast-Proxy',
+ 'ascend_max_shared_users' => 'Ascend-Max-Shared-Users',
'usr_bridging' => 'USR-Bridging',
- 'usr_originate_answer_mod' => 'USR-Originate-Answer-Mode',
+ 'cvx_presession_time' => 'CVX-PreSession-Time',
+ 'cvpn5000_vpn_groupinfo' => 'CVPN5000-VPN-GroupInfo',
+ 'autz_type' => 'Autz-Type',
'x_ascend_fr_dlci' => 'X-Ascend-FR-DLCI',
'usr_request_type' => 'USR-Request-Type',
- 'acc_dialout_auth_usernam' => 'Acc-Dialout-Auth-Username',
+ 'acc_igmp_admin_state' => 'Acc-Igmp-Admin-State',
'ascend_host_info' => 'Ascend-Host-Info',
+ 'ascend_dhcp_maximum_leas' => 'Ascend-DHCP-Maximum-Leases',
'usr_rmmie_num_of_updates' => 'USR-RMMIE-Num-Of-Updates',
'x_ascend_fr_profile_name' => 'X-Ascend-FR-Profile-Name',
'ascend_fr_direct_profile' => 'Ascend-FR-Direct-Profile',
'x_ascend_bridge' => 'X-Ascend-Bridge',
- 'tunnel_deadtime' => 'Tunnel_Deadtime',
+ 'tunnel_deadtime' => 'Tunnel-Deadtime',
'ms_chap_error' => 'MS-CHAP-Error',
'framed_route' => 'Framed-Route',
+ 'sip_from' => 'Sip-From',
'expiration' => 'Expiration',
'ascend_backup' => 'Ascend-Backup',
'ascend_pre_output_octets' => 'Ascend-Pre-Output-Octets',
+ 'ascend_calling_id_number' => 'Ascend-Calling-Id-Number-Plan',
'framed_appletalk_zone' => 'Framed-AppleTalk-Zone',
'annex_audit_level' => 'Annex-Audit-Level',
- 'bind_auth_context' => 'Bind_Auth_Context',
- 'cisco_asing_ip_pool' => 'Cisco-Asing-IP-Pool',
+ 'digest_algorithm' => 'Digest-Algorithm',
+ 'bind_auth_context' => 'Bind-Auth-Context',
'ascend_user_acct_base' => 'Ascend-User-Acct-Base',
- 'mcast_receive' => 'Mcast_Receive',
+ 'st_secondary_dns_server' => 'ST-Secondary-DNS-Server',
+ 'mcast_receive' => 'Mcast-Receive',
'usr_ds0' => 'USR-DS0',
+ 'aat_atm_traffic_profile' => 'AAT-ATM-Traffic-Profile',
'ms_ras_vendor' => 'MS-RAS-Vendor',
- 'tunnel_domain' => 'Tunnel_Domain',
- 'usr_secondary_nbns_serve' => 'USR-Secondary_NBNS_Server',
- 'tunnel_max_sessions' => 'Tunnel_Max_Sessions',
+ 'tunnel_domain' => 'Tunnel-Domain',
+ 'tunnel_max_sessions' => 'Tunnel-Max-Sessions',
'ascend_ip_direct' => 'Ascend-IP-Direct',
+ 'xedia_address_pool' => 'Xedia-Address-Pool',
'idle_timeout' => 'Idle-Timeout',
+ 'tunnel_rate_limit_ratf' => 'Tunnel_Rate_Limit_Rate',
+ 'annex_rate_reneg_req_sen' => 'Annex-Rate-Reneg-Req-Sent',
+ 'usr_initial_tx_link_data' => 'USR-Initial-Tx-Link-Data-Rate',
'tunnel_server_auth_id' => 'Tunnel-Server-Auth-Id',
+ 'cvpn3000_ipsec_banner1' => 'CVPN3000-IPSec-Banner1',
'usr_start_time' => 'USR-Start-Time',
'usr_ip' => 'USR-IP',
+ 'cvpn3000_reqrd_client_fw' => 'CVPN3000-Reqrd-Client-Fw-Vendor-Code',
+ 'altiga_ipsec_secondary_d' => 'Altiga-IPSec-Secondary-Domains-G',
'usr_gateway_ip_address' => 'USR-Gateway-IP-Address',
- 'usr_number_of_characters' => 'USR-Number-Of-Characters-Lost',
'ascend_dba_monitor' => 'Ascend-DBA-Monitor',
+ 'ms_link_utilization_thre' => 'MS-Link-Utilization-Threshold',
+ 'st_primary_dns_server' => 'ST-Primary-DNS-Server',
+ 'acc_ace_token_ttl' => 'Acc-Ace-Token-Ttl',
'ms_chap_domain' => 'MS-CHAP-Domain',
'cisco_pre_input_octets' => 'Cisco-Pre-Input-Octets',
+ 'ascend_primary_home_agen' => 'Ascend-Primary-Home-Agent',
'acct_session_time' => 'Acct-Session-Time',
'framed_ip_address' => 'Framed-IP-Address',
- 'x_ascend_ip_pool_definit' => 'X-Ascend-IP-Pool-Definition',
- 'erx_alternate_cli_access' => 'ERX-Alternate-Cli-Access-Level',
- 'medium_type' => 'Medium_Type',
- 'acct_output_octets_64' => 'Acct_Output_Octets_64',
+ 'ns_admin_privilege' => 'NS-Admin-Privilege',
+ 'medium_type' => 'Medium-Type',
+ 'acct_output_octets_64' => 'Acct-Output-Octets-64',
'ascend_cir_timer' => 'Ascend-CIR-Timer',
- 'police_rate' => 'Police_Rate',
+ 'police_rate' => 'Police-Rate',
+ 'tunnel_functioo' => 'Tunnel_Function',
+ 'quintum_h323_time_and_da' => 'Quintum-h323-time-and-day',
+ 'ip_tos_fiele' => 'IP_TOS_Field',
+ 'erx_framed_ip_route_tag' => 'ERX-Framed-Ip-Route-Tag',
'ms_mppe_send_key' => 'MS-MPPE-Send-Key',
- 'ascend_multicast_gleave_' => 'Ascend-Multicast-GLeave-Delay',
+ 'ascend_maximum_call_dura' => 'Ascend-Maximum-Call-Duration',
+ 'pppoe_motn' => 'PPPOE_MOTM',
+ 'lac_poru' => 'LAC_Port',
+ 'bind_dot1q_slou' => 'Bind_Dot1q_Slot',
+ 'ascend_secondary_home_ag' => 'Ascend-Secondary-Home-Agent',
+ 'usr_ip_call_output_filte' => 'USR-IP-Call-Output-Filter',
'x_ascend_host_info' => 'X-Ascend-Host-Info',
'erx_egress_policy_name' => 'ERX-Egress-Policy-Name',
+ 'erx_ppp_password' => 'ERX-PPP-Password',
'user_name' => 'User-Name',
- 'bind_bypass_bypass' => 'Bind_Bypass_Bypass',
+ 'usr_number_of_characters' => 'USR-Number-Of-Characters-Lost',
+ 'bind_bypass_bypass' => 'Bind-Bypass-Bypass',
+ 'usr_rad_multicast_routip' => 'USR-Rad-Multicast-Routing-Proto',
'annex_acct_servers' => 'Annex-Acct-Servers',
+ 'cvpn5000_tunnel_throughp' => 'CVPN5000-Tunnel-Throughput',
'usr_chassis_call_channel' => 'USR-Chassis-Call-Channel',
'annex_input_filter' => 'Annex-Input-Filter',
- 'ascend_home_agent_passwo' => 'Ascend-Home-Agent-Password',
+ 'wispr_billing_class_of_s' => 'WISPr-Billing-Class-Of-Service',
'nas_port_type' => 'NAS-Port-Type',
+ 'cvx_client_assign_dns' => 'CVX-Client-Assign-DNS',
+ 'nomadix_maxbytesdown' => 'Nomadix-MaxBytesDown',
'ascend_endpoint_disc' => 'Ascend-Endpoint-Disc',
- 'tunnel_police_burst' => 'Tunnel_Police_Burst',
- 'bind_auth_max_sessions' => 'Bind_Auth_Max_Sessions',
+ 'tunnel_police_burst' => 'Tunnel-Police-Burst',
+ 'bind_auth_max_sessions' => 'Bind-Auth-Max-Sessions',
+ 'cvx_identification' => 'CVX-Identification',
+ 'cvpn3000_ipsec_allow_pas' => 'CVPN3000-IPSec-Allow-Passwd-Store',
+ 'ascend_calling_id_type_o' => 'Ascend-Calling-Id-Type-Of-Num',
'x_ascend_fr_dce_n392' => 'X-Ascend-FR-DCE-N392',
'usr_connect_term_reason' => 'USR-Connect-Term-Reason',
- 'usr_mbi_ct_pri_card_span' => 'USR-Mbi_Ct_PRI_Card_Span_Line',
'erx_egress_statistics' => 'ERX-Egress-Statistics',
'ascend_fr_dte_n392' => 'Ascend-FR-DTE-N392',
'usr_esn' => 'USR-ESN',
'x_ascend_fr_dte_n392' => 'X-Ascend-FR-DTE-N392',
+ 'itk_modem_init_string' => 'ITK-Modem-Init-String',
'x_ascend_fr_nailed_grp' => 'X-Ascend-FR-Nailed-Grp',
'ascend_bridge_non_pppoe' => 'Ascend-Bridge-Non-PPPoE',
+ 'cvpn3000_ipsec_reqrd_cli' => 'CVPN3000-IPSec-Reqrd-Client-Fw-Cap',
'ascend_ipx_alias' => 'Ascend-IPX-Alias',
'acc_tunnel_port' => 'Acc-Tunnel-Port',
+ 'quintum_h323_return_code' => 'Quintum-h323-return-code',
+ 'cvpn3000_l2tp_encryption' => 'CVPN3000-L2TP-Encryption',
'acct_input_gigawords' => 'Acct-Input-Gigawords',
+ 'bind_dot1q_poru' => 'Bind_Dot1q_Port',
+ 'altiga_primary_wins_g' => 'Altiga-Primary-WINS-G',
'ascend_maximum_channels' => 'Ascend-Maximum-Channels',
+ 'x_ascend_home_agent_pass' => 'X-Ascend-Home-Agent-Password',
'x_ascend_ppp_async_map' => 'X-Ascend-PPP-Async-Map',
+ 'usr_rmmie_manufacturer_i' => 'USR-RMMIE-Manufacturer-ID',
'usr_retrains_requested' => 'USR-Retrains-Requested',
'x_ascend_metric' => 'X-Ascend-Metric',
'acc_apsm_oversubscribed' => 'Acc-Apsm-Oversubscribed',
+ 'usr_originate_answer_mod' => 'USR-Originate-Answer-Mode',
'erx_atm_pcr' => 'ERX-Atm-PCR',
+ 'itk_nas_name' => 'ITK-NAS-Name',
'usr_ipx_routing' => 'USR-IPX-Routing',
'usr_tunneled_mlpp' => 'USR-Tunneled-MLPP',
'usr_send_script5' => 'USR-Send-Script5',
'ascend_traffic_shaper' => 'Ascend-Traffic-Shaper',
+ 'ascend_client_secondarya' => 'Ascend-Client-Secondary-DNS',
'ascend_bacp_enable' => 'Ascend-BACP-Enable',
+ 'usr_call_terminate_in_gm' => 'USR-Call-Terminate-in-GMT',
'login_time' => 'Login-Time',
+ 'bg_path_cosu' => 'BG_Path_Cost',
+ 'aat_require_auth' => 'AAT-Require-Auth',
+ 'cvpn3000_reqrd_client_fy' => 'CVPN3000-Reqrd-Client-Fw-Description',
'ascend_call_type' => 'Ascend-Call-Type',
'erx_address_pool_name' => 'ERX-Address-Pool-Name',
+ 'cvpn3000_ipsec_backup_sf' => 'CVPN3000-IPSec-Backup-Server-List',
'h323_incoming_conf_id' => 'h323-incoming-conf-id',
+ 'user_profile' => 'User-Profile',
+ 'ip_host_adds' => 'Ip_Host_Addr',
+ 'ns_primary_wins' => 'NS-Primary-WINS',
'packet_type' => 'Packet-Type',
+ 'bind_auth_max_sessiont' => 'Bind_Auth_Max_Sessions',
+ 'altiga_allow_alpha_only_' => 'Altiga-Allow-Alpha-Only-Passwords-G',
'usr_security_resp_limit' => 'USR-Security-Resp-Limit',
- 'ip_address_pool_name' => 'Ip_Address_Pool_Name',
- 'ascend_cbcp_trunk_group' => 'Ascend-CBCP-Trunk-Group',
+ 'ip_address_pool_name' => 'Ip-Address-Pool-Name',
'ascend_ipx_node_addr' => 'Ascend-IPX-Node-Addr',
+ 'ascend_cbcp_trunk_group' => 'Ascend-CBCP-Trunk-Group',
'ascend_menu_selector' => 'Ascend-Menu-Selector',
+ 'ascend_assign_ip_global_' => 'Ascend-Assign-IP-Global-Pool',
'usr_ds0s' => 'USR-DS0s',
'usr_actual_voltage' => 'USR-Actual-Voltage',
+ 'quintum_h323_call_type' => 'Quintum-h323-call-type',
'annex_sw_version' => 'Annex-SW-Version',
- 'ascend_history_weigh_typ' => 'Ascend-History-Weigh-Type',
'ascend_receive_secret' => 'Ascend-Receive-Secret',
+ 'bintec_qospolicytable' => 'BinTec-qosPolicyTable',
'usr_ip_rip_policies' => 'USR-IP-RIP-Policies',
+ 'redcreek_tunneled_ip_add' => 'RedCreek-Tunneled-IP-Addr',
'ascend_pw_warntime' => 'Ascend-PW-Warntime',
- 'x_ascend_assign_ip_serve' => 'X-Ascend-Assign-IP-Server',
- 'tunnel_session_auth_serv' => 'Tunnel_Session_Auth_Service_Grp',
+ 'x_ascend_inc_channel_cou' => 'X-Ascend-Inc-Channel-Count',
'usr_blocks_resent' => 'USR-Blocks-Resent',
'usr_fallback_enabled' => 'USR-Fallback-Enabled',
'arap_challenge_response' => 'ARAP-Challenge-Response',
- 'tunnel_session_auth' => 'Tunnel_Session_Auth',
+ 'tunnel_session_auth' => 'Tunnel-Session-Auth',
'usr_sync_async_mode' => 'USR-Sync-Async-Mode',
+ 'itk_dialout_type' => 'ITK-Dialout-Type',
+ 'extreme_netlogin_url' => 'Extreme-Netlogin-Url',
'client_port_dnis' => 'Client-Port-DNIS',
+ 'digest_realm' => 'Digest-Realm',
'ascend_ppp_vj_1172' => 'Ascend-PPP-VJ-1172',
- 'ascend_remote_addr' => 'Ascend-Remote-Addr',
'ascend_fr_n391' => 'Ascend-FR-N391',
+ 'ascend_remote_addr' => 'Ascend-Remote-Addr',
'client_port_id' => 'Client-Port-Id',
- 'usr_num_fax_pages_proces' => 'USR-Num-Fax-Pages-Processed',
+ 'digest_body_digest' => 'Digest-Body-Digest',
'le_ipsec_active_profile' => 'LE-IPSec-Active-Profile',
+ 'digest_cnonce' => 'Digest-CNonce',
'usr_port_tap_facility' => 'USR-Port-Tap-Facility',
'usr_callback_type' => 'USR-Callback-Type',
+ 'client_dns_prj' => 'Client_DNS_Pri',
+ 'digest_response' => 'Digest-Response',
'login_lat_group' => 'Login-LAT-Group',
'x_ascend_call_type' => 'X-Ascend-Call-Type',
'ascend_route_ip' => 'Ascend-Route-IP',
+ 'usr_rad_multicast_routio' => 'USR-Rad-Multicast-Routing-RtLim',
'usr_pw_vpn_id' => 'USR-PW_VPN_ID',
- 'le_nat_sess_dir_fail_act' => 'LE-NAT-Sess-Dir-Fail-Action',
+ 'cvx_modem_end_modulation' => 'CVX-Modem-End-Modulation',
+ 'cvpn3000_pptp_mppc_compr' => 'CVPN3000-PPTP-MPPC-Compression',
'cisco_pre_output_octets' => 'Cisco-Pre-Output-Octets',
'h323_billing_model' => 'h323-billing-model',
'usr_equalization_type' => 'USR-Equalization-Type',
'acc_clearing_cause' => 'Acc-Clearing-Cause',
+ 'altiga_access_hours_g_u' => 'Altiga-Access-Hours-G/U',
+ 'cvpn3000_ipsec_user_grou' => 'CVPN3000-IPSec-User-Group-Lock',
'x_ascend_menu_selector' => 'X-Ascend-Menu-Selector',
'x_ascend_netware_timeout' => 'X-Ascend-Netware-timeout',
'ascend_fr_linkup' => 'Ascend-FR-LinkUp',
- 'police_burst' => 'Police_Burst',
+ 'annex_num_in_multilink' => 'Annex-Num-In-Multilink',
+ 'police_burst' => 'Police-Burst',
+ 'altiga_l2tp_min_authenti' => 'Altiga-L2TP-Min-Authentication-G/U',
'ascend_filter_required' => 'Ascend-Filter-Required',
- 'usr_compression_algorith' => 'USR-Compression-Algorithm',
- 'le_ipsec_outsource_profi' => 'LE-IPSec-Outsource-Profile',
'x_ascend_idle_limit' => 'X-Ascend-Idle-Limit',
- 'usr_call_terminate_in_gm' => 'USR-Call-Terminate-in-GMT',
- 'usr_ipx_call_output_filt' => 'USR-IPX-Call-Output-Filter',
- 'ip_tos_field' => 'IP_TOS_Field',
+ 'nomadix_logoff_url' => 'Nomadix-Logoff-URL',
+ 'cvpn3000_ms_client_icpt_' => 'CVPN3000-MS-Client-Icpt-DHCP-Conf-Msg',
+ 'ip_tos_field' => 'IP-TOS-Field',
'ascend_ip_tos_apply_to' => 'Ascend-IP-TOS-Apply-To',
- 'tunnel_l2f_second_passwo' => 'Tunnel_L2F_Second_Password',
'usr_call_event_code' => 'USR-Call-Event-Code',
+ 'usr_et_bridge_output_fil' => 'USR-ET-Bridge-Output-Filter',
+ 'le_nat_sess_dir_fail_act' => 'LE-NAT-Sess-Dir-Fail-Action',
'usr_rmmie_product_code' => 'USR-RMMIE-Product-Code',
'usr_host_type' => 'USR-Host-Type',
+ 'erx_tunnel_interface_id' => 'ERX-Tunnel-Interface-Id',
'ascend_send_auth' => 'Ascend-Send-Auth',
'shiva_compression_type' => 'Shiva-Compression-Type',
- 'filter_id' => 'Filter-Id',
+ 'itk_banner' => 'ITK-Banner',
'ascend_ft1_caller' => 'Ascend-FT1-Caller',
- 'erx_cli_initial_access_l' => 'ERX-Cli-Initial-Access-Level',
+ 'filter_id' => 'Filter-Id',
+ 'annex_pre_output_octets' => 'Annex-Pre-Output-Octets',
+ 'acct_mcast_in_octett' => 'Acct_Mcast_In_Octets',
'usr_log_filter_packets' => 'USR-Log-Filter-Packets',
'ascend_fr_nailed_grp' => 'Ascend-FR-Nailed-Grp',
- 'usr_initial_tx_link_data' => 'USR-Initial-Tx-Link-Data-Rate',
+ 'ascend_atm_loopback_cell' => 'Ascend-ATM-Loopback-Cell-Loss',
+ 'usr_at_rtmp_output_filte' => 'USR-AT-RTMP-Output-Filter',
'acc_input_errors' => 'Acc-Input-Errors',
'x_ascend_user_acct_port' => 'X-Ascend-User-Acct-Port',
'erx_secondary_wins' => 'ERX-Secondary-Wins',
'usr_rmmie_serial_number' => 'USR-RMMIE-Serial-Number',
- 'ascend_client_primary_dn' => 'Ascend-Client-Primary-DNS',
+ 'usr_et_bridge_input_filt' => 'USR-ET-Bridge-Input-Filter',
+ 'ns_primary_dns' => 'NS-Primary-DNS',
'usr_slot_connected_to' => 'USR-Slot-Connected-To',
'shiva_disconnect_reason' => 'Shiva-Disconnect-Reason',
+ 'cvpn5000_client_assignee' => 'CVPN5000-Client-Assigned-IPX',
+ 'cvx_radius_redirect' => 'CVX-Radius-Redirect',
'usr_receive_acc_map' => 'USR-Receive-Acc-Map',
- 'usr_compression_reset_mo' => 'USR-Compression-Reset-Mode',
- 'usr_rmmie_planned_discon' => 'USR-RMMIE-Planned-Disconnect',
- 'ascend_client_assign_dns' => 'Ascend-Client-Assign-DNS',
+ 'x_ascend_tunneling_proto' => 'X-Ascend-Tunneling-Protocol',
+ 'itk_acct_serv_ip' => 'ITK-Acct-Serv-IP',
'ascend_fr_type' => 'Ascend-FR-Type',
+ 'ascend_client_assign_dns' => 'Ascend-Client-Assign-DNS',
+ 'annex_retrain_requests_r' => 'Annex-Retrain-Requests-Rcvd',
+ 'x_ascend_assign_ip_globa' => 'X-Ascend-Assign-IP-Global-Pool',
'tunnel_client_endpoint' => 'Tunnel-Client-Endpoint',
+ 'alteon_service_type' => 'Alteon-Service-Type',
'x_ascend_send_secret' => 'X-Ascend-Send-Secret',
'x_ascend_call_filter' => 'X-Ascend-Call-Filter',
'usr_ipx_rip_input_filter' => 'USR-IPX-RIP-Input-Filter',
'x_ascend_maximum_time' => 'X-Ascend-Maximum-Time',
- 'ascend_x25_pad_x3_profil' => 'Ascend-X25-Pad-X3-Profile',
- 'pvc_profile_name' => 'PVC_Profile_Name',
+ 'pvc_profile_name' => 'PVC-Profile-Name',
+ 'usr_framed_ip_address_po' => 'USR-Framed_IP_Address_Pool_Name',
+ 'cvpn3000_ipsec_split_dns' => 'CVPN3000-IPSec-Split-DNS-Names',
'ascend_global_call_id' => 'Ascend-Global-Call-Id',
- 'tunnel_local_name' => 'Tunnel_Local_Name',
+ 'usr_initial_rx_link_data' => 'USR-Initial-Rx-Link-Data-Rate',
+ 'st_primary_nbns_server' => 'ST-Primary-NBNS-Server',
+ 'usr_number_of_rings_limi' => 'USR-Number-of-Rings-Limit',
+ 'tunnel_local_name' => 'Tunnel-Local-Name',
'ascend_fr_t392' => 'Ascend-FR-T392',
- 'usr_dnis_reauthenticatio' => 'USR-DNIS-ReAuthentication',
- 'ascend_pre_output_packet' => 'Ascend-Pre-Output-Packets',
+ 'annex_pool_id' => 'Annex-Pool-Id',
'ascend_token_immediate' => 'Ascend-Token-Immediate',
+ 'usr_rmmie_firmware_build' => 'USR-RMMIE-Firmware-Build-Date',
+ 'wispr_bandwidth_min_down' => 'WISPr-Bandwidth-Min-Down',
'usr_chassis_call_slot' => 'USR-Chassis-Call-Slot',
- 'rate_limit_burst' => 'Rate_Limit_Burst',
+ 'rate_limit_burst' => 'Rate-Limit-Burst',
'cisco_route_ip' => 'Cisco-Route-IP',
- 'dhcp_max_leases' => 'DHCP_Max_Leases',
+ 'xedia_netbios_server' => 'Xedia-NetBios-Server',
+ 'session_error_msg' => 'Session-Error-Msg',
+ 'dhcp_max_leases' => 'DHCP-Max-Leases',
+ 'acc_vpsm_reject_cause' => 'Acc-Vpsm-Reject-Cause',
'user_category' => 'User-Category',
- 'x_ascend_maximum_call_du' => 'X-Ascend-Maximum-Call-Duration',
- 'bind_type' => 'Bind_Type',
+ 'x_ascend_multicast_rate_' => 'X-Ascend-Multicast-Rate-Limit',
+ 'cvpn3000_ipsec_auth_on_r' => 'CVPN3000-IPSec-Auth-On-Rekey',
+ 'altiga_min_password_leng' => 'Altiga-Min-Password-Length-G',
+ 'bind_type' => 'Bind-Type',
+ 'ascend_tunneling_protoco' => 'Ascend-Tunneling-Protocol',
+ 'cvx_modem_retx_packets' => 'CVX-Modem-ReTx-Packets',
'usr_framed_ipx_route' => 'USR-Framed-IPX-Route',
- 'rate_limit_rate' => 'Rate_Limit_Rate',
+ 'rate_limit_rate' => 'Rate-Limit-Rate',
'ascend_atm_connect_vpi' => 'Ascend-ATM-Connect-Vpi',
- 'x_ascend_inc_channel_cou' => 'X-Ascend-Inc-Channel-Count',
'connect_info' => 'Connect-Info',
- 'x_ascend_pre_input_packe' => 'X-Ascend-Pre-Input-Packets',
'usr_port_tap_address' => 'USR-Port-Tap-Address',
- 'ascend_home_agent_udp_po' => 'Ascend-Home-Agent-UDP-Port',
- 'usr_final_rx_link_data_r' => 'USR-Final-Rx-Link-Data-Rate',
+ 'usr_simplified_mnp_level' => 'USR-Simplified-MNP-Levels',
+ 'mcast_receivf' => 'Mcast_Receive',
+ 'annex_begin_modulation' => 'Annex-Begin-Modulation',
'usr_pw_usr_ifilter_ip' => 'USR-PW_USR_IFilter_IP',
'ascend_route_appletalk' => 'Ascend-Route-Appletalk',
'ms_chap_lm_enc_pw' => 'MS-CHAP-LM-Enc-PW',
+ 'altiga_ipsec_over_nat_po' => 'Altiga-IPSec-Over-NAT-Port-Num-G',
+ 'itk_isdn_prot' => 'ITK-ISDN-Prot',
'ascend_callback_delay' => 'Ascend-Callback-Delay',
+ 'session_error_code' => 'Session-Error-Code',
+ 'nomadix_endofsession' => 'Nomadix-EndofSession',
'x_ascend_bacp_enable' => 'X-Ascend-BACP-Enable',
- 'bg_trans_bpdu' => 'BG_Trans_BPDU',
+ 'bg_trans_bpdu' => 'BG-Trans-BPDU',
+ 'bind_int_interface_namf' => 'Bind_Int_Interface_Name',
+ 'foundry_privilege_level' => 'Foundry-Privilege-Level',
'huntgroup_name' => 'Huntgroup-Name',
'x_ascend_ipx_alias' => 'X-Ascend-IPX-Alias',
- 'x_ascend_secondary_home_' => 'X-Ascend-Secondary-Home-Agent',
+ 'tunnel_l2f_second_passwp' => 'Tunnel_L2F_Second_Password',
+ 'xedia_dns_server' => 'Xedia-DNS-Server',
'usr_ipx_wan' => 'USR-IPX-WAN',
+ 'annex_addr_resolution_se' => 'Annex-Addr-Resolution-Servers',
+ 'acct_output_octets_65' => 'Acct_Output_Octets_64',
'menu' => 'Menu',
+ 'erx_tunnel_nas_port_meth' => 'ERX-Tunnel-Nas-Port-Method',
+ 'aat_output_octets_diff' => 'AAT-Output-Octets-Diff',
'x_ascend_fr_direct_dlci' => 'X-Ascend-FR-Direct-DLCI',
'acct_status_type' => 'Acct-Status-Type',
'ascend_port_redir_server' => 'Ascend-Port-Redir-Server',
+ 'telebit_port_name' => 'Telebit-Port-Name',
'acc_dns_server_sec' => 'Acc-Dns-Server-Sec',
+ 'cvx_modem_remote_retrain' => 'CVX-Modem-Remote-Retrains',
'ascend_minimum_channels' => 'Ascend-Minimum-Channels',
- 'ascend_telnet_profile' => 'Ascend-Telnet-Profile',
'ascend_ipx_route' => 'Ascend-IPX-Route',
+ 'ascend_telnet_profile' => 'Ascend-Telnet-Profile',
'usr_call_connect_in_gmt' => 'USR-Call-Connect-in-GMT',
+ 'usr_cusr_hat_script_rule' => 'USR-CUSR-hat-Script-Rules',
'x_ascend_dba_monitor' => 'X-Ascend-DBA-Monitor',
+ 'response_packet_type' => 'Response-Packet-Type',
'usr_event_id' => 'USR-Event-Id',
+ 'cvpn3000_ipsec_over_udp_' => 'CVPN3000-IPSec-Over-UDP-Port',
'ascend_inc_channel_count' => 'Ascend-Inc-Channel-Count',
'usr_send_script3' => 'USR-Send-Script3',
+ 'annex_pre_input_packets' => 'Annex-Pre-Input-Packets',
'framed_callback_id' => 'Framed-Callback-Id',
+ 'xedia_client_access_netw' => 'Xedia-Client-Access-Network',
'arap_zone_access' => 'ARAP-Zone-Access',
+ 'ascend_port_redir_portnu' => 'Ascend-Port-Redir-Portnum',
'service_type' => 'Service-Type',
'usr_nfas_id' => 'USR-NFAS-ID',
'shiva_calling_number' => 'Shiva-Calling-Number',
'ascend_user_acct_host' => 'Ascend-User-Acct-Host',
+ 'tunnel_session_auth_serv' => 'Tunnel-Session-Auth-Service-Grp',
+ 'juniper_deny_commands' => 'Juniper-Deny-Commands',
'ascend_fr_link_mgt' => 'Ascend-FR-Link-Mgt',
+ 'nokia_imsi' => 'Nokia-IMSI',
+ 'quintum_h323_prompt_id' => 'Quintum-h323-prompt-id',
+ 'cvpn3000_require_individ' => 'CVPN3000-Require-Individual-User-Auth',
+ 'tunnel_retransmiu' => 'Tunnel_Retransmit',
+ 'source_validatioo' => 'Source_Validation',
+ 'sip_to' => 'Sip-To',
'ms_primary_nbns_server' => 'MS-Primary-NBNS-Server',
'quintum_avpair' => 'Quintum-AVPair',
- 'x_ascend_home_agent_pass' => 'X-Ascend-Home-Agent-Password',
'ascend_transit_number' => 'Ascend-Transit-Number',
'ascend_cache_refresh' => 'Ascend-Cache-Refresh',
- 'versanet_termination_cau' => 'Versanet-Termination-Cause',
'ascend_user_acct_type' => 'Ascend-User-Acct-Type',
+ 'usr_num_fax_pages_proces' => 'USR-Num-Fax-Pages-Processed',
'usr_mic' => 'USR-MIC',
- 'ascend_base_channel_coun' => 'Ascend-Base-Channel-Count',
- 'x_ascend_dhcp_pool_numbe' => 'X-Ascend-DHCP-Pool-Number',
+ 'usr_failure_to_connect_r' => 'USR-Failure-to-Connect-Reason',
+ 'cisco_fax_auth_status' => 'Cisco-Fax-Auth-Status',
+ 'bind_dot1q_vlan_tag_ie' => 'Bind_Dot1q_Vlan_Tag_Id',
'ms_chap2_success' => 'MS-CHAP2-Success',
+ 'erx_tunnel_virtual_route' => 'ERX-Tunnel-Virtual-Router',
'cisco_idle_limit' => 'Cisco-Idle-Limit',
'ascend_pw_lifetime' => 'Ascend-PW-Lifetime',
+ 'cvpn3000_access_hours' => 'CVPN3000-Access-Hours',
+ 'bintec_sapcirctable' => 'BinTec-sapCircTable',
'usr_packet_bus_session' => 'USR-Packet-Bus-Session',
- 'ascend_atm_loopback_cell' => 'Ascend-ATM-Loopback-Cell-Loss',
- 'acct_input_packets_64' => 'Acct_Input_Packets_64',
+ 'acct_input_packets_64' => 'Acct-Input-Packets-64',
+ 'ascend_x25_pad_x3_parame' => 'Ascend-X25-Pad-X3-Parameters',
+ 'usr_secondary_nbns_serve' => 'USR-Secondary_NBNS_Server',
'ascend_modem_slotno' => 'Ascend-Modem-SlotNo',
+ 'digest_qop' => 'Digest-QOP',
'usr_characters_received' => 'USR-Characters-Received',
+ 'rate_limit_ratf' => 'Rate_Limit_Rate',
'ms_bap_usage' => 'MS-BAP-Usage',
'cisco_data_filter' => 'Cisco-Data-Filter',
- 'ascend_seconds_of_histor' => 'Ascend-Seconds-Of-History',
+ 'usr_simplified_v42bis_us' => 'USR-Simplified-V42bis-Usage',
'h323_setup_time' => 'h323-setup-time',
- 'acc_dialout_auth_passwor' => 'Acc-Dialout-Auth-Password',
+ 'annex_wan_number' => 'Annex-Wan-Number',
+ 'cvx_vpop_id' => 'CVX-VPOP-ID',
+ 'usr_pw_tunnel_authentica' => 'USR-PW_Tunnel_Authentication',
'le_nat_outsource_inmap' => 'LE-NAT-Outsource-Inmap',
+ 'cvx_modem_begin_recv_lin' => 'CVX-Modem-Begin-Recv-Line-Lvl',
+ 'telebit_login_command' => 'Telebit-Login-Command',
+ 'cisco_command_code' => 'Cisco-Command-Code',
+ 'itk_ppp_auth_type' => 'ITK-PPP-Auth-Type',
+ 'bintec_qosiftable' => 'BinTec-qosIfTable',
+ 'x_ascend_mpp_idle_percen' => 'X-Ascend-MPP-Idle-Percent',
'usr_sap_filter_in' => 'USR-SAP-Filter-In',
'framed_appletalk_link' => 'Framed-AppleTalk-Link',
- 'usr_initial_rx_link_data' => 'USR-Initial-Rx-Link-Data-Rate',
- 'usr_ospf_addressless_ind' => 'USR-OSPF-Addressless-Index',
+ 'tunnel_domaio' => 'Tunnel_Domain',
'usr_ipx' => 'USR-IPX',
+ 'nas_real_poru' => 'NAS_Real_Port',
'shiva_connect_reason' => 'Shiva-Connect-Reason',
+ 'x_ascend_pre_output_octe' => 'X-Ascend-Pre-Output-Octets',
'cisco_ppp_vj_slot_comp' => 'Cisco-PPP-VJ-Slot-Comp',
+ 'freeradius_proxied_to' => 'Freeradius-Proxied-To',
'ascend_atm_vpi' => 'Ascend-ATM-Vpi',
'acc_ml_mlx_admin_state' => 'Acc-ML-MLX-Admin-State',
+ 'cvx_modem_snr' => 'CVX-Modem-SNR',
'usr_igmp_robustness' => 'USR-IGMP-Robustness',
+ 'annex_rate_reneg_req_rcv' => 'Annex-Rate-Reneg-Req-Rcvd',
'add_prefix' => 'Add-Prefix',
'x_ascend_call_by_call' => 'X-Ascend-Call-By-Call',
- 'x_ascend_connect_progres' => 'X-Ascend-Connect-Progress',
+ 'usr_last_callers_number_' => 'USR-Last-Callers-Number-ANI',
+ 'postauth_type' => 'PostAuth-Type',
+ 'pvc_circuit_paddinh' => 'PVC_Circuit_Padding',
'usr_at_rtmp_input_filter' => 'USR-AT-RTMP-Input-Filter',
'erx_igmp_enable' => 'ERX-Igmp-Enable',
- 'usr_rmmie_rcv_pwrlvl_375' => 'USR-RMMIE-Rcv-PwrLvl-3750Hz',
+ 'bind_bypass_contexu' => 'Bind_Bypass_Context',
+ 'x_ascend_num_in_multilin' => 'X-Ascend-Num-In-Multilink',
'usr_pw_packet' => 'USR-PW_Packet',
'dialback_no' => 'Dialback-No',
'ascend_ip_tos_precedence' => 'Ascend-IP-TOS-Precedence',
+ 'cvpn5000_vpn_password' => 'CVPN5000-VPN-Password',
'annex_cli_filter' => 'Annex-CLI-Filter',
'x_ascend_dial_number' => 'X-Ascend-Dial-Number',
'usr_iwf_call_identifier' => 'USR-IWF-Call-Identifier',
'ms_secondary_dns_server' => 'MS-Secondary-DNS-Server',
- 'ascend_client_secondary_' => 'Ascend-Client-Secondary-WINS',
'shiva_type_of_service' => 'Shiva-Type-Of-Service',
- 'usr_framed_ip_address_po' => 'USR-Framed_IP_Address_Pool_Name',
- 'bind_ses_context' => 'Bind_Ses_Context',
+ 'bind_ses_context' => 'Bind-Ses-Context',
'acc_reason_code' => 'Acc-Reason-Code',
'ms_chap_cpw_1' => 'MS-CHAP-CPW-1',
+ 'wispr_bandwidth_max_down' => 'WISPr-Bandwidth-Max-Down',
'h323_call_type' => 'h323-call-type',
+ 'bind_bypass_bypast' => 'Bind_Bypass_Bypass',
+ 'usr_number_of_link_timeo' => 'USR-Number-of-Link-Timeouts',
'ascend_fr_08_mode' => 'Ascend-FR-08-Mode',
'usr_calling_party_number' => 'USR-Calling-Party-Number',
- 'usr_rad_multicast_routin' => 'USR-Rad-Multicast-Routing-RtLim',
'usr_reply_script2' => 'USR-Reply-Script2',
'usr_security_login_limit' => 'USR-Security-Login-Limit',
'cisco_link_compression' => 'Cisco-Link-Compression',
- 'usr_et_bridge_output_fil' => 'USR-ET-Bridge-Output-Filter',
'ascend_vrouter_name' => 'Ascend-VRouter-Name',
+ 'erx_ppp_auth_protocol' => 'ERX-PPP-Auth-Protocol',
+ 'x_ascend_call_block_dura' => 'X-Ascend-Call-Block-Duration',
'usr_modem_setup_time' => 'USR-Modem-Setup-Time',
+ 'pppoe_urm' => 'PPPOE_URL',
'cisco_ip_direct' => 'Cisco-IP-Direct',
'x_ascend_temporary_rtes' => 'X-Ascend-Temporary-Rtes',
'ascend_x25_pad_alias_3' => 'Ascend-X25-Pad-Alias-3',
- 'usr_rmmie_pwrlvl_xmit_lv' => 'USR-RMMIE-PwrLvl-Xmit-Lvl',
+ 'annex_multilink_id' => 'Annex-Multilink-Id',
+ 'mcast_maxgroupt' => 'Mcast_MaxGroups',
'configuration_token' => 'Configuration-Token',
- 'usr_at_rtmp_output_filte' => 'USR-AT-RTMP-Output-Filter',
- 'usr_ip_default_route_opt' => 'USR-IP-Default-Route-Option',
- 'ascend_calling_subaddres' => 'Ascend-Calling-Subaddress',
+ 'ascend_h323_conference_i' => 'Ascend-H323-Conference-Id',
+ 'ascend_ipx_header_compre' => 'Ascend-IPX-Header-Compression',
'stripped_user_name' => 'Stripped-User-Name',
+ 'usr_ipx_rip_output_filte' => 'USR-IPX-RIP-Output-Filter',
'cisco_call_filter' => 'Cisco-Call-Filter',
+ 'nas_ipv6_address' => 'NAS-IPv6-Address',
'termination_menu' => 'Termination-Menu',
+ 'ascend_shared_profile_en' => 'Ascend-Shared-Profile-Enable',
'port_message' => 'Port-Message',
- 'usr_igmp_maximum_respons' => 'USR-IGMP-Maximum-Response-Time',
'erx_ingress_policy_name' => 'ERX-Ingress-Policy-Name',
- 'ascend_call_attempt_limi' => 'Ascend-Call-Attempt-Limit',
'acc_service_profile' => 'Acc-Service-Profile',
'ascend_bir_proxy' => 'Ascend-BIR-Proxy',
+ 'aat_ppp_address' => 'AAT-PPP-Address',
+ 'usr_mbi_ct_pri_card_span' => 'USR-Mbi_Ct_PRI_Card_Span_Line',
'ascend_x25_nui_prompt' => 'Ascend-X25-Nui-Prompt',
- 'usr_rmmie_pwrlvl_noise_l' => 'USR-RMMIE-PwrLvl-Noise-Lvl',
- 'usr_rmmie_pwrlvl_nearech' => 'USR-RMMIE-PwrLvl-NearEcho-Canc',
- 'x_ascend_multicast_clien' => 'X-Ascend-Multicast-Client',
+ 'itk_modem_pool_id' => 'ITK-Modem-Pool-Id',
+ 'usr_compression_reset_mo' => 'USR-Compression-Reset-Mode',
'usr_unauthenticated_time' => 'USR-Unauthenticated-Time',
+ 'ascend_multicast_gleave_' => 'Ascend-Multicast-GLeave-Delay',
'acc_callback_cbcp_type' => 'Acc-Callback-CBCP-Type',
+ 'medium_typf' => 'Medium_Type',
'login_service' => 'Login-Service',
- 'usr_rad_multicast_routin' => 'USR-Rad-Multicast-Routing-Bound',
+ 'itk_username_prompt' => 'ITK-Username-Prompt',
'ascend_dial_number' => 'Ascend-Dial-Number',
+ 'framed_ipv6_route' => 'Framed-IPv6-Route',
'x_ascend_remote_addr' => 'X-Ascend-Remote-Addr',
- 'usr_rmmie_rcv_pwrlvl_330' => 'USR-RMMIE-Rcv-PwrLvl-3300Hz',
'usr_call_end_date_time' => 'USR-Call-End-Date-Time',
- 'bind_dot1q_slot' => 'Bind_Dot1q_Slot',
+ 'bind_dot1q_slot' => 'Bind-Dot1q-Slot',
'le_connect_detail' => 'LE-Connect-Detail',
'annex_user_level' => 'Annex-User-Level',
- 'tunnel_dnis' => 'Tunnel_DNIS',
- 'assigned_ip_address' => 'Assigned_IP_Address',
+ 'tunnel_dnis' => 'Tunnel-DNIS',
+ 'assigned_ip_address' => 'Assigned-IP-Address',
'acc_bridging_support' => 'Acc-Bridging-Support',
'usr_channel' => 'USR-Channel',
'arap_security_data' => 'ARAP-Security-Data',
- 'bind_auth_service_grp' => 'Bind_Auth_Service_Grp',
- 'x_ascend_pre_output_pack' => 'X-Ascend-Pre-Output-Packets',
- 'x_ascend_seconds_of_hist' => 'X-Ascend-Seconds-Of-History',
+ 'bind_auth_service_grp' => 'Bind-Auth-Service-Grp',
+ 'cisco_abort_cause' => 'Cisco-Abort-Cause',
+ 'bg_span_dit' => 'BG_Span_Dis',
'h323_voice_quality' => 'h323-voice-quality',
- 'usr_rmmie_last_update_ti' => 'USR-RMMIE-Last-Update-Time',
- 'usr_disconnect_cause_ind' => 'USR-Disconnect-Cause-Indicator',
+ 'lac_real_port_typf' => 'LAC_Real_Port_Type',
'usr_channel_connected_to' => 'USR-Channel-Connected-To',
- 'ascend_calling_id_number' => 'Ascend-Calling-Id-Number-Plan',
+ 'ascend_client_assign_win' => 'Ascend-Client-Assign-WINS',
+ 'redcreek_tunneled_gatewa' => 'RedCreek-Tunneled-Gateway',
'usr_number_of_fallbacks' => 'USR-Number-of-Fallbacks',
- 'usr_ip_call_output_filte' => 'USR-IP-Call-Output-Filter',
+ 'nokia_prepaid_ind' => 'Nokia-Prepaid-Ind',
+ 'nomadix_maxbytesup' => 'Nomadix-MaxBytesUp',
+ 'login_hosu' => 'Login-Host',
'ascend_bir_enable' => 'Ascend-BIR-Enable',
'usr_connect_time_limit' => 'USR-Connect-Time-Limit',
'ascend_presession_time' => 'Ascend-PreSession-Time',
- 'ascend_private_route_req' => 'Ascend-Private-Route-Required',
- 'ascend_dsl_cir_xmit_limi' => 'Ascend-Dsl-CIR-Xmit-Limit',
+ 'altiga_simultaneous_logi' => 'Altiga-Simultaneous-Logins-G/U',
+ 'cvpn3000_ipsec_default_d' => 'CVPN3000-IPSec-Default-Domain',
+ 'aat_atm_vci' => 'AAT-ATM-VCI',
+ 'extreme_netlogin_url_des' => 'Extreme-Netlogin-Url-Desc',
+ 'itk_auth_serv_ip' => 'ITK-Auth-Serv-IP',
+ 'erx_alternate_cli_vroute' => 'ERX-Alternate-Cli-Vrouter-Name',
'framed_compression' => 'Framed-Compression',
'ascend_svc_enabled' => 'Ascend-SVC-Enabled',
'proxy_state' => 'Proxy-State',
- 'ascend_tunnel_vrouter_na' => 'Ascend-Tunnel-VRouter-Name',
- 'usr_ipx_call_input_filte' => 'USR-IPX-Call-Input-Filter',
- 'x_ascend_assign_ip_globa' => 'X-Ascend-Assign-IP-Global-Pool',
- 'erx_alternate_cli_vroute' => 'ERX-Alternate-Cli-Vrouter-Name',
- 'ascend_dhcp_maximum_leas' => 'Ascend-DHCP-Maximum-Leases',
+ 'aat_vrouter_name' => 'AAT-Vrouter-Name',
+ 'usr_rmmie_pwrlvl_farecho' => 'USR-RMMIE-PwrLvl-FarEcho-Canc',
+ 'nas_poru' => 'NAS-Port',
+ 'wispr_location_name' => 'WISPr-Location-Name',
+ 'digest_user_name' => 'Digest-User-Name',
'ascend_modem_shelfno' => 'Ascend-Modem-ShelfNo',
- 'bind_auth_protocol' => 'Bind_Auth_Protocol',
'shasta_user_privilege' => 'Shasta-User-Privilege',
+ 'bind_auth_protocol' => 'Bind-Auth-Protocol',
+ 'ascend_home_agent_passwo' => 'Ascend-Home-Agent-Password',
'acct_interim_interval' => 'Acct-Interim-Interval',
+ 'ascend_history_weigh_typ' => 'Ascend-History-Weigh-Type',
+ 'ms_link_drop_time_limit' => 'MS-Link-Drop-Time-Limit',
'hint' => 'Hint',
'x_ascend_target_util' => 'X-Ascend-Target-Util',
- 'ms_link_drop_time_limit' => 'MS-Link-Drop-Time-Limit',
'acc_access_partition' => 'Acc-Access-Partition',
- 'x_ascend_multilink_id' => 'X-Ascend-Multilink-ID',
'usr_power_supply_number' => 'USR-Power-Supply-Number',
- 'acc_ipx_compression' => 'Acc-Ipx-Compression',
+ 'x_ascend_multilink_id' => 'X-Ascend-Multilink-ID',
+ 'redcreek_tunneled_domain' => 'RedCreek-Tunneled-DomainName',
'nomadix_bw_down' => 'Nomadix-Bw-Down',
- 'usr_call_reference_numbe' => 'USR-Call-Reference-Number',
+ 'acc_ipx_compression' => 'Acc-Ipx-Compression',
+ 'quintum_h323_setup_time' => 'Quintum-h323-setup-time',
'cisco_target_util' => 'Cisco-Target-Util',
- 'usr_back_channel_data_ra' => 'USR-Back-Channel-Data-Rate',
'acc_ip_gateway_sec' => 'Acc-Ip-Gateway-Sec',
- 'usr_dte_ring_no_answer_l' => 'USR-DTE-Ring-No-Answer-Limit',
- 'usr_connect_time' => 'USR-Connect-Time',
+ 'ascend_dsl_cir_xmit_limi' => 'Ascend-Dsl-CIR-Xmit-Limit',
'ascend_ip_pool_definitio' => 'Ascend-IP-Pool-Definition',
+ 'bind_sub_user_at_contexu' => 'Bind_Sub_User_At_Context',
+ 'itk_dest_no' => 'ITK-Dest-No',
+ 'usr_connect_time' => 'USR-Connect-Time',
'usr_call_start_date_time' => 'USR-Call-Start-Date-Time',
+ 'altiga_l2tp_encryption_g' => 'Altiga-L2TP-Encryption-G',
+ 'ascend_auth_delay' => 'Ascend-Auth-Delay',
+ 'ascend_x25_pad_x3_profil' => 'Ascend-X25-Pad-X3-Profile',
+ 'ascend_access_intercepta' => 'Ascend-Access-Intercept-Log',
+ 'ascend_home_agent_udp_po' => 'Ascend-Home-Agent-UDP-Port',
+ 'bind_tun_context' => 'Bind-Tun-Context',
'dialback_name' => 'Dialback-Name',
- 'bind_tun_context' => 'Bind_Tun_Context',
'h323_redirect_ip_address' => 'h323-redirect-ip-address',
'annex_keypress_timeout' => 'Annex-Keypress-Timeout',
+ 'x_ascend_home_network_na' => 'X-Ascend-Home-Network-Name',
'ascend_x25_pad_alias_1' => 'Ascend-X25-Pad-Alias-1',
+ 'ascend_call_attempt_limi' => 'Ascend-Call-Attempt-Limit',
+ 'quintum_h323_currency_ty' => 'Quintum-h323-currency-type',
'ms_chap_response' => 'MS-CHAP-Response',
+ 'st_secondary_nbns_server' => 'ST-Secondary-NBNS-Server',
+ 'x_ascend_history_weigh_t' => 'X-Ascend-History-Weigh-Type',
'usr_max_channels' => 'USR-Max-Channels',
'ascend_fr_dte_n393' => 'Ascend-FR-DTE-N393',
'ascend_pre_input_octets' => 'Ascend-Pre-Input-Octets',
'erx_atm_mbs' => 'ERX-Atm-MBS',
+ 'cvpn3000_simultaneous_lo' => 'CVPN3000-Simultaneous-Logins',
+ 'juniper_allow_commands' => 'Juniper-Allow-Commands',
'usr_line_reversals' => 'USR-Line-Reversals',
+ 'itk_users_default_pw' => 'ITK-Users-Default-Pw',
'x_ascend_third_prompt' => 'X-Ascend-Third-Prompt',
+ 'cisco_fax_msg_id' => 'Cisco-Fax-Msg-Id',
'x_ascend_pw_warntime' => 'X-Ascend-PW-Warntime',
'ascend_data_filter' => 'Ascend-Data-Filter',
'framed_address' => 'Framed-Address',
'context_name' => 'Context-Name',
'usr_send_script2' => 'USR-Send-Script2',
'ms_arap_pw_change_reason' => 'MS-ARAP-PW-Change-Reason',
+ 'tunnel_session_auth_cty' => 'Tunnel_Session_Auth_Ctx',
'acct_session_id' => 'Acct-Session-Id',
+ 'annex_port' => 'Annex-Port',
+ 'quintum_h323_call_origin' => 'Quintum-h323-call-origin',
+ 'erx_cli_initial_access_l' => 'ERX-Cli-Initial-Access-Level',
+ 'x_ascend_shared_profile_' => 'X-Ascend-Shared-Profile-Enable',
+ 'tunnel_cmd_timeouu' => 'Tunnel_Cmd_Timeout',
'initial_modulation_type' => 'Initial-Modulation-Type',
'ascend_h323_gatekeeper' => 'Ascend-H323-Gatekeeper',
'x_ascend_fcp_parameter' => 'X-Ascend-FCP-Parameter',
- 'tunnel_type' => 'Tunnel-Type',
'multi_link_flag' => 'Multi-Link-Flag',
+ 'tunnel_type' => 'Tunnel-Type',
+ 'erx_output_gigapkts' => 'ERX-Output-Gigapkts',
'ascend_idle_limit' => 'Ascend-Idle-Limit',
+ 'ns_user_group' => 'NS-User-Group',
'password_retry' => 'Password-Retry',
'h323_remote_address' => 'h323-remote-address',
'erx_atm_service_category' => 'ERX-Atm-Service-Category',
'acct_input_packets' => 'Acct-Input-Packets',
'h323_disconnect_time' => 'h323-disconnect-time',
- 'ascend_billing_number' => 'Ascend-Billing-Number',
'usr_syslog_tap' => 'USR-Syslog-Tap',
+ 'telebit_accounting_info' => 'Telebit-Accounting-Info',
+ 'ascend_billing_number' => 'Ascend-Billing-Number',
+ 'ascend_tunnel_vrouter_na' => 'Ascend-Tunnel-VRouter-Name',
'ms_mppe_encryption_type' => 'MS-MPPE-Encryption-Type',
+ 'quintum_h323_credit_amou' => 'Quintum-h323-credit-amount',
+ 'acc_ace_token' => 'Acc-Ace-Token',
'ascend_assign_ip_pool' => 'Ascend-Assign-IP-Pool',
+ 'annex_end_modulation' => 'Annex-End-Modulation',
'usr_routing_protocol' => 'USR-Routing-Protocol',
+ 'cvx_assign_ip_pool' => 'CVX-Assign-IP-Pool',
'usr_rad_location_type' => 'USR-Rad-Location-Type',
+ 'usr_rmmie_pwrlvl_noise_l' => 'USR-RMMIE-PwrLvl-Noise-Lvl',
'usr_characters_sent' => 'USR-Characters-Sent',
'usr_mp_edo_hiper' => 'USR-MP-EDO-HIPER',
+ 'ascend_x25_nui_password_' => 'Ascend-X25-Nui-Password-Prompt',
'annex_host_restrict' => 'Annex-Host-Restrict',
'user_service_type' => 'User-Service-Type',
'acct_multi_session_id' => 'Acct-Multi-Session-Id',
'ms_chap_cpw_2' => 'MS-CHAP-CPW-2',
- 'x_ascend_primary_home_ag' => 'X-Ascend-Primary-Home-Agent',
+ 'x_ascend_secondary_home_' => 'X-Ascend-Secondary-Home-Agent',
'x_ascend_dialout_allowed' => 'X-Ascend-Dialout-Allowed',
'ascend_connect_progress' => 'Ascend-Connect-Progress',
'x_ascend_ara_pw' => 'X-Ascend-Ara-PW',
+ 'cisco_fax_modem_time' => 'Cisco-Fax-Modem-Time',
+ 'sql_group' => 'Sql-Group',
+ 'annex_multicast_rate_lim' => 'Annex-Multicast-Rate-Limit',
+ 'cvpn3000_user_auth_servg' => 'CVPN3000-User-Auth-Server-Secret',
'ns_mta_md5_password' => 'NS-MTA-MD5-Password',
+ 'annex_addr_resolution_pr' => 'Annex-Addr-Resolution-Protocol',
'callback_number' => 'Callback-Number',
- 'acct_output_packets_64' => 'Acct_Output_Packets_64',
+ 'cvx_multilink_match_info' => 'CVX-Multilink-Match-Info',
+ 'tunnel_max_tunnelt' => 'Tunnel_Max_Tunnels',
+ 'tunnel_local_namf' => 'Tunnel_Local_Name',
+ 'quintum_h323_conf_id' => 'Quintum-h323-conf-id',
+ 'acct_output_packets_64' => 'Acct-Output-Packets-64',
+ 'annex_signal_to_noise_ra' => 'Annex-Signal-to-Noise-Ratio',
+ 'acct_output_packets_65' => 'Acct_Output_Packets_64',
'x_ascend_user_acct_key' => 'X-Ascend-User-Acct-Key',
+ 'erx_dial_out_number' => 'ERX-Dial-Out-Number',
'ascend_modem_portno' => 'Ascend-Modem-PortNo',
'ascend_assign_ip_server' => 'Ascend-Assign-IP-Server',
'ascend_fcp_parameter' => 'Ascend-FCP-Parameter',
- 'ascend_inter_arrival_jit' => 'Ascend-Inter-Arrival-Jitter',
+ 'usr_chassis_temp_thresho' => 'USR-Chassis-Temp-Threshold',
+ 'usr_mpip_tunnel_originat' => 'USR-MPIP-Tunnel-Originator',
+ 'tunnel_rate_limit_bursu' => 'Tunnel_Rate_Limit_Burst',
'client_ip_address' => 'Client-IP-Address',
- 'usr_number_of_link_timeo' => 'USR-Number-of-Link-Timeouts',
- 'ascend_dsl_cir_recv_limi' => 'Ascend-Dsl-CIR-Recv-Limit',
+ 'le_nat_tcp_session_timeo' => 'LE-NAT-TCP-Session-Timeout',
+ 'quintum_h323_redirect_ip' => 'Quintum-h323-redirect-ip-address',
'ms_acct_eap_type' => 'MS-Acct-EAP-Type',
- 'x_ascend_user_acct_type' => 'X-Ascend-User-Acct-Type',
'usr_rmmie_x2_status' => 'USR-RMMIE-x2-Status',
- 'ascend_dsl_downstream_li' => 'Ascend-Dsl-Downstream-Limit',
+ 'x_ascend_user_acct_type' => 'X-Ascend-User-Acct-Type',
'shiva_customer_id' => 'Shiva-Customer-Id',
- 'lac_real_port' => 'LAC_Real_Port',
+ 'pvc_encapsulation_typf' => 'PVC_Encapsulation_Type',
+ 'st_acct_vc_connection_id' => 'ST-Acct-VC-Connection-Id',
+ 'lac_real_port' => 'LAC-Real-Port',
'h323_connect_time' => 'h323-connect-time',
- 'old_password' => 'Old-Password',
'usr_vpn_gw_location_id' => 'USR-VPN-GW-Location-Id',
+ 'old_password' => 'Old-Password',
'x_ascend_if_netmask' => 'X-Ascend-IF-Netmask',
'add_suffix' => 'Add-Suffix',
- 'x_ascend_client_assign_d' => 'X-Ascend-Client-Assign-DNS',
- 'usr_q931_call_reference_' => 'USR-Q931-Call-Reference-Value',
+ 'lac_port_typf' => 'LAC_Port_Type',
+ 'acc_ip_pool_name' => 'Acc-Ip-Pool-Name',
'usr_terminal_type' => 'USR-Terminal-Type',
'usr_spoofing' => 'USR-Spoofing',
'erx_tunnel_password' => 'ERX-Tunnel-Password',
- 'ascend_assign_ip_client' => 'Ascend-Assign-IP-Client',
+ 'ascend_inter_arrival_jit' => 'Ascend-Inter-Arrival-Jitter',
+ 'ascend_call_block_durati' => 'Ascend-Call-Block-Duration',
+ 'itk_channel_binding' => 'ITK-Channel-Binding',
'usr_server_time' => 'USR-Server-Time',
+ 'ascend_assign_ip_client' => 'Ascend-Assign-IP-Client',
+ 'erx_pppoe_max_sessions' => 'ERX-Pppoe-Max-Sessions',
+ 'cvx_multilink_group_numb' => 'CVX-Multilink-Group-Number',
+ 'x_ascend_client_assign_d' => 'X-Ascend-Client-Assign-DNS',
+ 'erx_pppoe_url' => 'ERX-Pppoe-Url',
+ 'police_ratf' => 'Police_Rate',
'ascend_data_svc' => 'Ascend-Data-Svc',
'annex_authen_servers' => 'Annex-Authen-Servers',
'nomadix_bw_up' => 'Nomadix-Bw-Up',
+ 'cvx_modem_data_compressi' => 'CVX-Modem-Data-Compression',
'shiva_link_speed' => 'Shiva-Link-Speed',
'usr_reply_script6' => 'USR-Reply-Script6',
'usr_expansion_algorithm' => 'USR-Expansion-Algorithm',
- 'x_ascend_mpp_idle_percen' => 'X-Ascend-MPP-Idle-Percent',
+ 'cabletron_protocol_calla' => 'Cabletron-Protocol-Callable',
'cisco_data_rate' => 'Cisco-Data-Rate',
'usr_primary_dns_server' => 'USR-Primary_DNS_Server',
- 'erx_local_loopback_inter' => 'ERX-Local-Loopback-Interface',
+ 'juniper_deny_configurati' => 'Juniper-Deny-Configuration',
'ascend_target_util' => 'Ascend-Target-Util',
- 'usr_default_dte_data_rat' => 'USR-Default-DTE-Data-Rate',
+ 'digest_method' => 'Digest-Method',
+ 'altiga_ipsec_split_tunne' => 'Altiga-IPSec-Split-Tunnel-List-G',
+ 'erx_alternate_cli_access' => 'ERX-Alternate-Cli-Access-Level',
'x_ascend_event_type' => 'X-Ascend-Event-Type',
+ 'usr_q931_call_reference_' => 'USR-Q931-Call-Reference-Value',
'usr_mp_mrru' => 'USR-MP-MRRU',
- 'bind_bypass_context' => 'Bind_Bypass_Context',
+ 'cvx_ipsvc_mask' => 'CVX-IPSVC-Mask',
+ 'bind_bypass_context' => 'Bind-Bypass-Context',
+ 'usr_rmmie_last_update_ev' => 'USR-RMMIE-Last-Update-Event',
'no_such_attribute' => 'No-Such-Attribute',
- 'acct_mcast_out_packets' => 'Acct_Mcast_Out_Packets',
+ 'acct_mcast_out_packets' => 'Acct-Mcast-Out-Packets',
'tunnel_medium_type' => 'Tunnel-Medium-Type',
+ 'quintum_h323_remote_addr' => 'Quintum-h323-remote-address',
'acc_callback_delay' => 'Acc-Callback-Delay',
- 'x_ascend_home_agent_udp_' => 'X-Ascend-Home-Agent-UDP-Port',
- 'acct_input_octets_64' => 'Acct_Input_Octets_64',
+ 'acct_input_octets_64' => 'Acct-Input-Octets-64',
+ 'ascend_base_channel_coun' => 'Ascend-Base-Channel-Count',
'ascend_atm_connect_vci' => 'Ascend-ATM-Connect-Vci',
'erx_primary_dns' => 'ERX-Primary-Dns',
+ 'altiga_ipsec_over_nat_g' => 'Altiga-IPSec-Over-NAT-G',
+ 'cvx_multicast_rate_limit' => 'CVX-Multicast-Rate-Limit',
'ascend_xmit_rate' => 'Ascend-Xmit-Rate',
'ms_new_arap_password' => 'MS-New-ARAP-Password',
'usr_call_error_code' => 'USR-Call-Error-Code',
'acct_output_octets' => 'Acct-Output-Octets',
- 'usr_failure_to_connect_r' => 'USR-Failure-to-Connect-Reason',
+ 'ascend_client_primary_wi' => 'Ascend-Client-Primary-WINS',
+ 'cvpn3000_primary_wins' => 'CVPN3000-Primary-WINS',
+ 'bintec_ipextrttable' => 'BinTec-ipExtRtTable',
+ 'cisco_fax_mdn_flag' => 'Cisco-Fax-Mdn-Flag',
+ 'ascend_destination_nas_p' => 'Ascend-Destination-Nas-Port',
'ascend_num_in_multilink' => 'Ascend-Num-In-Multilink',
+ 'digest_attributes' => 'Digest-Attributes',
+ 'cvpn3000_ipsec_tunnel_ty' => 'CVPN3000-IPSec-Tunnel-Type',
'x_ascend_number_sessions' => 'X-Ascend-Number-Sessions',
'usr_ip_rip_output_filter' => 'USR-IP-RIP-Output-Filter',
- 'usr_chassis_temp_thresho' => 'USR-Chassis-Temp-Threshold',
+ 'tunnel_police_bursu' => 'Tunnel_Police_Burst',
+ 'redcreek_tunneled_wins_s' => 'RedCreek-Tunneled-WINS-Server1',
'usr_blocks_sent' => 'USR-Blocks-Sent',
+ 'erx_cli_allow_all_vr_acc' => 'ERX-Cli-Allow-All-VR-Access',
+ 'tunnel_police_ratf' => 'Tunnel_Police_Rate',
'usr_ids0_call_type' => 'USR-IDS0-Call-Type',
'acc_ccp_option' => 'Acc-Ccp-Option',
'ascend_client_gateway' => 'Ascend-Client-Gateway',
- 'x_ascend_multicast_rate_' => 'X-Ascend-Multicast-Rate-Limit',
+ 'cvx_maximum_channels' => 'CVX-Maximum-Channels',
+ 'bg_aging_timf' => 'BG_Aging_Time',
+ 'annex_secondary_dns_serv' => 'Annex-Secondary-DNS-Server',
'le_ipsec_passive_profile' => 'LE-IPSec-Passive-Profile',
'usr_chassis_call_span' => 'USR-Chassis-Call-Span',
- 'usr_mobileip_home_agent_' => 'USR-MobileIP-Home-Agent-Address',
+ 'aat_client_primary_wins_' => 'AAT-Client-Primary-WINS-NBNS',
+ 'h323_currency' => 'h323-currency',
'password' => 'Password',
'le_nat_log_options' => 'LE-NAT-Log-Options',
- 'x_ascend_ppp_address' => 'X-Ascend-PPP-Address',
'usr_fallback_limit' => 'USR-Fallback-Limit',
+ 'x_ascend_ppp_address' => 'X-Ascend-PPP-Address',
'suffix' => 'Suffix',
'usr_multicast_receive' => 'USR-Multicast-Receive',
- 'client_dns_sec' => 'Client_DNS_Sec',
+ 'client_dns_sec' => 'Client-DNS-Sec',
'annex_product_name' => 'Annex-Product-Name',
'cisco_pw_lifetime' => 'Cisco-PW-Lifetime',
'x_ascend_fr_dce_n393' => 'X-Ascend-FR-DCE-N393',
'x_ascend_ts_idle_limit' => 'X-Ascend-TS-Idle-Limit',
- 'usr_last_number_dialed_o' => 'USR-Last-Number-Dialed-Out',
- 'mcast_send' => 'Mcast_Send',
- 'pppoe_motm' => 'PPPOE_MOTM',
+ 'mcast_send' => 'Mcast-Send',
+ 'x_ascend_primary_home_ag' => 'X-Ascend-Primary-Home-Agent',
+ 'tunnel_max_sessiont' => 'Tunnel_Max_Sessions',
+ 'pppoe_motm' => 'PPPOE-MOTM',
'usr_pw_usr_ifilter_ipx' => 'USR-PW_USR_IFilter_IPX',
- 'usr_pw_tunnel_authentica' => 'USR-PW_Tunnel_Authentication',
- 'ascend_source_ip_check' => 'Ascend-Source-IP-Check',
- 'ascend_assign_ip_global_' => 'Ascend-Assign-IP-Global-Pool',
'ms_ras_version' => 'MS-RAS-Version',
- 'usr_rad_multicast_routin' => 'USR-Rad-Multicast-Routing-Ttl',
- 'x_ascend_modem_slotno' => 'X-Ascend-Modem-SlotNo',
+ 'ascend_source_ip_check' => 'Ascend-Source-IP-Check',
+ 'bintec_ospfiftable' => 'BinTec-ospfIfTable',
'acc_ml_call_threshold' => 'Acc-ML-Call-Threshold',
+ 'x_ascend_modem_slotno' => 'X-Ascend-Modem-SlotNo',
'ascend_menu_item' => 'Ascend-Menu-Item',
- 'usr_cdma_call_reference_' => 'USR-CDMA-Call-Reference-Number',
'callback_id' => 'Callback-Id',
'framed_ipx_network' => 'Framed-IPX-Network',
- 'x_ascend_disconnect_caus' => 'X-Ascend-Disconnect-Cause',
+ 'altiga_pptp_encryption_g' => 'Altiga-PPTP-Encryption-G',
+ 'ascend_x25_reverse_charg' => 'Ascend-X25-Reverse-Charging',
'ascend_user_acct_key' => 'Ascend-User-Acct-Key',
'x_ascend_pw_lifetime' => 'X-Ascend-PW-Lifetime',
'user_name_is_star' => 'User-Name-Is-Star',
- 'x_ascend_authen_alias' => 'X-Ascend-Authen-Alias',
+ 'nomadix_url_redirection' => 'Nomadix-URL-Redirection',
'framed_pool' => 'Framed-Pool',
+ 'x_ascend_authen_alias' => 'X-Ascend-Authen-Alias',
+ 'cisco_fax_dsn_address' => 'Cisco-Fax-Dsn-Address',
'ms_primary_dns_server' => 'MS-Primary-DNS-Server',
+ 'acc_dialout_auth_usernam' => 'Acc-Dialout-Auth-Username',
'realm' => 'Realm',
'arap_features' => 'ARAP-Features',
+ 'bind_auth_protocom' => 'Bind_Auth_Protocol',
'acc_connect_tx_speed' => 'Acc-Connect-Tx-Speed',
- 'usr_last_number_dialed_i' => 'USR-Last-Number-Dialed-In-DNIS',
'usr_chassis_temperature' => 'USR-Chassis-Temperature',
+ 'altiga_ipsec_mode_config' => 'Altiga-IPSec-Mode-Config-G',
+ 'ascend_home_agent_ip_add' => 'Ascend-Home-Agent-IP-Addr',
'x_ascend_xmit_rate' => 'X-Ascend-Xmit-Rate',
+ 'cvpn3000_secondary_dns' => 'CVPN3000-Secondary-DNS',
'x_ascend_send_passwd' => 'X-Ascend-Send-Passwd',
+ 'bind_int_contexu' => 'Bind_Int_Context',
+ 'cisco_fax_account_id_ori' => 'Cisco-Fax-Account-Id-Origin',
'le_modem_info' => 'LE-Modem-Info',
'ascend_ipx_peer_mode' => 'Ascend-IPX-Peer-Mode',
- 'le_nat_other_session_tim' => 'LE-NAT-Other-Session-Timeout',
- 'tunnel_rate_limit_rate' => 'Tunnel_Rate_Limit_Rate',
- 'ascend_maximum_call_dura' => 'Ascend-Maximum-Call-Duration',
+ 'juniper_local_user_name' => 'Juniper-Local-User-Name',
+ 'tunnel_rate_limit_rate' => 'Tunnel-Rate-Limit-Rate',
+ 'quintum_h323_credit_time' => 'Quintum-h323-credit-time',
+ 'acc_modem_modulation_typ' => 'Acc-Modem-Modulation-Type',
+ 'x_ascend_seconds_of_hist' => 'X-Ascend-Seconds-Of-History',
'ascend_dhcp_pool_number' => 'Ascend-DHCP-Pool-Number',
+ 'redcreek_tunneled_ip_net' => 'RedCreek-Tunneled-IP-Netmask',
'x_ascend_callback' => 'X-Ascend-Callback',
- 'ascend_access_intercept_' => 'Ascend-Access-Intercept-Log',
'usr_iwf_ip_address' => 'USR-IWF-IP-Address',
+ 'aat_input_octets_diff' => 'AAT-Input-Octets-Diff',
'nas_port_id' => 'NAS-Port-Id',
'le_advice_of_charge' => 'LE-Advice-of-Charge',
+ 'x_ascend_dhcp_pool_numbe' => 'X-Ascend-DHCP-Pool-Number',
'ascend_add_seconds' => 'Ascend-Add-Seconds',
'annex_transmit_speed' => 'Annex-Transmit-Speed',
'usr_port_tap' => 'USR-Port-Tap',
'usr_at_call_input_filter' => 'USR-AT-Call-Input-Filter',
+ 'framed_ipv6_pool' => 'Framed-IPv6-Pool',
'ascend_qos_downstream' => 'Ascend-QOS-Downstream',
- 'ascend_x25_reverse_charg' => 'Ascend-X25-Reverse-Charging',
- 'lac_port' => 'LAC_Port',
+ 'lac_port' => 'LAC-Port',
'tunnel_assignment_id' => 'Tunnel-Assignment-Id',
+ 'acct_mcast_out_octett' => 'Acct_Mcast_Out_Octets',
+ 'ascend_bi_directional_au' => 'Ascend-Bi-Directional-Auth',
'fall_through' => 'Fall-Through',
+ 'cvpn3000_ipsec_ip_compre' => 'CVPN3000-IPSec-IP-Compression',
'cisco_disconnect_cause' => 'Cisco-Disconnect-Cause',
- 'module_message' => 'Module-Message',
+ 'usr_rad_multicast_routiq' => 'USR-Rad-Multicast-Routing-Bound',
+ 'altiga_tunneling_protoco' => 'Altiga-Tunneling-Protocols-G/U',
+ 'itk_tunnel_prot' => 'ITK-Tunnel-Prot',
+ 'client_dns_sed' => 'Client_DNS_Sec',
'framed_ip_netmask' => 'Framed-IP-Netmask',
+ 'usr_call_reference_numbe' => 'USR-Call-Reference-Number',
'ascend_egress_enabled' => 'Ascend-Egress-Enabled',
'ascend_dsl_rate_mode' => 'Ascend-Dsl-Rate-Mode',
- 'x_ascend_client_primary_' => 'X-Ascend-Client-Primary-DNS',
'usr_pw_usr_ofilter_sap' => 'USR-PW_USR_OFilter_SAP',
+ 'bintec_iproutetable' => 'BinTec-ipRouteTable',
'acct_terminate_cause' => 'Acct-Terminate-Cause',
'x_ascend_fr_dte_n393' => 'X-Ascend-FR-DTE-N393',
- 'x_ascend_call_block_dura' => 'X-Ascend-Call-Block-Duration',
'ascend_ppp_address' => 'Ascend-PPP-Address',
+ 'erx_maximum_bps' => 'ERX-Maximum-BPS',
'caller_id' => 'Caller-ID',
- 'bind_int_interface_name' => 'Bind_Int_Interface_Name',
- 'x_ascend_ppp_vj_slot_com' => 'X-Ascend-PPP-VJ-Slot-Comp',
+ 'bintec_ipfiltertable' => 'BinTec-ipFilterTable',
+ 'x_ascend_base_channel_co' => 'X-Ascend-Base-Channel-Count',
+ 'bind_int_interface_name' => 'Bind-Int-Interface-Name',
'usr_modem_group' => 'USR-Modem-Group',
'cisco_maximum_channels' => 'Cisco-Maximum-Channels',
+ 'erx_ppp_username' => 'ERX-PPP-Username',
'ascend_link_compression' => 'Ascend-Link-Compression',
+ 'annex_retransmitted_pack' => 'Annex-Retransmitted-Packets',
'usr_retrains_granted' => 'USR-Retrains-Granted',
'ascend_dropped_packets' => 'Ascend-Dropped-Packets',
+ 'erx_bearer_type' => 'ERX-Bearer-Type',
'usr_pw_usr_ofilter_ip' => 'USR-PW_USR_OFilter_IP',
'quintum_nas_port' => 'Quintum-NAS-Port',
+ 'x_ascend_pre_output_pack' => 'X-Ascend-Pre-Output-Packets',
+ 'usr_cdma_call_reference_' => 'USR-CDMA-Call-Reference-Number',
+ 'tunnel_function' => 'Tunnel-Function',
'annex_tunnel_authen_mode' => 'Annex-Tunnel-Authen-Mode',
- 'tunnel_function' => 'Tunnel_Function',
'usr_mp_edo' => 'USR-MP-EDO',
'le_nat_outmap' => 'LE-NAT-Outmap',
+ 'cvpn3000_primary_dns' => 'CVPN3000-Primary-DNS',
'usr_modulation_type' => 'USR-Modulation-Type',
+ 'ascend_calling_id_screen' => 'Ascend-Calling-Id-Screening',
'ascend_maximum_time' => 'Ascend-Maximum-Time',
+ 'user_password' => 'User-Password',
'annex_callback_portlist' => 'Annex-Callback-Portlist',
- 'x_ascend_remove_seconds' => 'X-Ascend-Remove-Seconds',
+ 'cvpn3000_ipsec_split_tun' => 'CVPN3000-IPSec-Split-Tunnel-List',
+ 'annex_pre_output_packets' => 'Annex-Pre-Output-Packets',
+ 'usr_at_call_output_filte' => 'USR-AT-Call-Output-Filter',
+ 'x_ascend_client_primary_' => 'X-Ascend-Client-Primary-DNS',
'tunnel_server_endpoint' => 'Tunnel-Server-Endpoint',
+ 'x_ascend_remove_seconds' => 'X-Ascend-Remove-Seconds',
+ 'cvpn3000_user_auth_serve' => 'CVPN3000-User-Auth-Server-Name',
'arap_password' => 'ARAP-Password',
+ 'x_ascend_assign_ip_serve' => 'X-Ascend-Assign-IP-Server',
+ 'cisco_fax_pages' => 'Cisco-Fax-Pages',
'ms_chap_mppe_keys' => 'MS-CHAP-MPPE-Keys',
'ascend_source_auth' => 'Ascend-Source-Auth',
'group' => 'Group',
'usr_send_script6' => 'USR-Send-Script6',
'le_nat_inmap' => 'LE-NAT-Inmap',
'chap_password' => 'CHAP-Password',
- 'annex_primary_nbns_serve' => 'Annex-Primary-NBNS-Server',
'annex_receive_speed' => 'Annex-Receive-Speed',
- 'usr_rmmie_manufacturer_i' => 'USR-RMMIE-Manufacturer-ID',
- 'bind_l2tp_flow_control' => 'Bind_L2TP_Flow_Control',
+ 'usr_mobileip_home_agent_' => 'USR-MobileIP-Home-Agent-Address',
+ 'bind_l2tp_flow_control' => 'Bind-L2TP-Flow-Control',
'smb_account_ctrl' => 'SMB-Account-CTRL',
- 'ascend_calling_id_presen' => 'Ascend-Calling-Id-Presentatn',
'ascend_ip_pool_chaining' => 'Ascend-IP-Pool-Chaining',
'le_admin_group' => 'LE-Admin-Group',
- 'nas_identifier' => 'NAS-Identifier',
- 'x_ascend_history_weigh_t' => 'X-Ascend-History-Weigh-Type',
'tunnel_connection_id' => 'Tunnel-Connection-Id',
- 'nas_real_port' => 'NAS_Real_Port',
+ 'tunnel_windox' => 'Tunnel_Window',
+ 'nas_identifier' => 'NAS-Identifier',
+ 'dhcp_max_leaset' => 'DHCP_Max_Leases',
+ 'digest_nonce_count' => 'Digest-Nonce-Count',
+ 'nas_real_port' => 'NAS-Real-Port',
'ms_old_arap_password' => 'MS-Old-ARAP-Password',
- 'usr_ip_rip_simple_auth_p' => 'USR-IP-RIP-Simple-Auth-Password',
- 'erx_primary_wins' => 'ERX-Primary-Wins',
'usr_pw_index' => 'USR-PW_Index',
- 'erx_cli_allow_all_vr_acc' => 'ERX-Cli-Allow-All-VR-Access',
+ 'erx_primary_wins' => 'ERX-Primary-Wins',
+ 'ascend_appletalk_peer_mo' => 'Ascend-Appletalk-Peer-Mode',
'le_ipsec_log_options' => 'LE-IPSec-Log-Options',
- 'ascend_home_agent_ip_add' => 'Ascend-Home-Agent-IP-Addr',
+ 'x_ascend_maximum_channel' => 'X-Ascend-Maximum-Channels',
+ 'cvx_ipsvc_aznlvl' => 'CVX-IPSVC-AZNLVL',
+ 'x_ascend_client_secondar' => 'X-Ascend-Client-Secondary-DNS',
'annex_re_chap_timeout' => 'Annex-Re-CHAP-Timeout',
- 'usr_final_tx_link_data_r' => 'USR-Final-Tx-Link-Data-Rate',
- 'client_dns_pri' => 'Client_DNS_Pri',
+ 'aat_ip_pool_definition' => 'AAT-IP-Pool-Definition',
+ 'client_dns_pri' => 'Client-DNS-Pri',
+ 'cisco_service_info' => 'Cisco-Service-Info',
'usr_primary_nbns_server' => 'USR-Primary_NBNS_Server',
- 'usr_cusr_hat_script_rule' => 'USR-CUSR-hat-Script-Rules',
- 'ascend_multicast_rate_li' => 'Ascend-Multicast-Rate-Limit',
- 'usr_rmmie_pwrlvl_farecho' => 'USR-RMMIE-PwrLvl-FarEcho-Canc',
+ 'aat_atm_direct' => 'AAT-ATM-Direct',
+ 'bind_ses_contexu' => 'Bind_Ses_Context',
+ 'sip_translated_request_u' => 'Sip-Translated-Request-URI',
'acc_acct_on_off_reason' => 'Acc-Acct-On-Off-Reason',
'le_multicast_client' => 'LE-Multicast-Client',
+ 'bind_sub_passwore' => 'Bind_Sub_Password',
+ 'cvpn3000_cisco_ip_phone_' => 'CVPN3000-Cisco-IP-Phone-Bypass',
'ascend_send_passwd' => 'Ascend-Send-Passwd',
- 'annex_unauthenticated_ti' => 'Annex-Unauthenticated-Time',
- 'tunnel_context' => 'Tunnel_Context',
- 'acc_nbns_server_sec' => 'Acc-Nbns-Server-Sec',
+ 'tunnel_remote_namf' => 'Tunnel_Remote_Name',
+ 'cvx_disconnect_cause' => 'CVX-Disconnect-Cause',
+ 'itk_auth_serv_prot' => 'ITK-Auth-Serv-Prot',
+ 'tunnel_context' => 'Tunnel-Context',
+ 'digest_uri' => 'Digest-URI',
'usr_channel_decrement' => 'USR-Channel-Decrement',
- 'usr_rmmie_firmware_versi' => 'USR-RMMIE-Firmware-Version',
+ 'acc_nbns_server_sec' => 'Acc-Nbns-Server-Sec',
'ms_chap_challenge' => 'MS-CHAP-Challenge',
- 'x_ascend_client_secondar' => 'X-Ascend-Client-Secondary-DNS',
+ 'cisco_assign_ip_pool' => 'Cisco-Assign-IP-Pool',
'ascend_cbcp_mode' => 'Ascend-CBCP-Mode',
'ascend_x25_rpoa' => 'Ascend-X25-Rpoa',
'usr_dtr_false_timeout' => 'USR-DTR-False-Timeout',
- 'usr_rad_multicast_routin' => 'USR-Rad-Multicast-Routing-Proto',
- 'ascend_x25_pad_x3_parame' => 'Ascend-X25-Pad-X3-Parameters',
+ 'acct_dyn_ac_enu' => 'Acct_Dyn_Ac_Ent',
'usr_physical_state' => 'USR-Physical-State',
+ 'x_ascend_ppp_vj_slot_com' => 'X-Ascend-PPP-VJ-Slot-Comp',
+ 'x_ascend_link_compressio' => 'X-Ascend-Link-Compression',
'ascend_fr_t391' => 'Ascend-FR-T391',
- 'bind_dot1q_port' => 'Bind_Dot1q_Port',
- 'lac_port_type' => 'LAC_Port_Type',
- 'bg_aging_time' => 'BG_Aging_Time',
+ 'bind_dot1q_port' => 'Bind-Dot1q-Port',
+ 'ns_secondary_dns' => 'NS-Secondary-DNS',
+ 'altiga_ipsec_tunnel_type' => 'Altiga-IPSec-Tunnel-Type-G',
+ 'lac_port_type' => 'LAC-Port-Type',
+ 'bg_aging_time' => 'BG-Aging-Time',
'erx_atm_scr' => 'ERX-Atm-SCR',
+ 'x_ascend_pre_input_octet' => 'X-Ascend-Pre-Input-Octets',
+ 'cisco_fax_connect_speed' => 'Cisco-Fax-Connect-Speed',
'x_ascend_menu_item' => 'X-Ascend-Menu-Item',
+ 'quintum_h323_voice_quali' => 'Quintum-h323-voice-quality',
'ascend_x25_pad_banner' => 'Ascend-X25-Pad-Banner',
+ 'module_failure_message' => 'Module-Failure-Message',
'h323_gw_id' => 'h323-gw-id',
'h323_preferred_lang' => 'h323-preferred-lang',
'usr_min_compression_size' => 'USR-Min-Compression-Size',
'usr_compression_type' => 'USR-Compression-Type',
- 'x_ascend_call_attempt_li' => 'X-Ascend-Call-Attempt-Limit',
+ 'bintec_ipxstaticroutetab' => 'BinTec-ipxStaticRouteTable',
'ascend_dialout_allowed' => 'Ascend-Dialout-Allowed',
'annex_local_username' => 'Annex-Local-Username',
'cisco_pre_input_packets' => 'Cisco-Pre-Input-Packets',
- 'ascend_send_secret' => 'Ascend-Send-Secret',
'shiva_function' => 'Shiva-Function',
- 'usr_dte_data_idle_timout' => 'USR-DTE-Data-Idle-Timout',
+ 'ascend_send_secret' => 'Ascend-Send-Secret',
'usr_number_of_blers' => 'USR-Number-of-Blers',
+ 'usr_dte_data_idle_timout' => 'USR-DTE-Data-Idle-Timout',
'usr_card_type' => 'USR-Card-Type',
- 'ascend_token_idle' => 'Ascend-Token-Idle',
+ 'x_ascend_connect_progres' => 'X-Ascend-Connect-Progress',
'x_ascend_group' => 'X-Ascend-Group',
+ 'ascend_token_idle' => 'Ascend-Token-Idle',
+ 'erx_qos_profile_interfac' => 'ERX-Qos-Profile-Interface-Type',
+ 'ascend_private_route_tab' => 'Ascend-Private-Route-Table-ID',
'nt_password' => 'NT-Password',
- 'acct_mcast_in_packets' => 'Acct_Mcast_In_Packets',
+ 'acct_mcast_in_packets' => 'Acct-Mcast-In-Packets',
+ 'x_ascend_multicast_clien' => 'X-Ascend-Multicast-Client',
'usr_supports_tags' => 'USR-Supports-Tags',
+ 'cvpn3000_authd_user_idle' => 'CVPN3000-Authd-User-Idle-Timeout',
'ascend_number_sessions' => 'Ascend-Number-Sessions',
'x_ascend_add_seconds' => 'X-Ascend-Add-Seconds',
'usr_number_of_upshifts' => 'USR-Number-of-Upshifts',
'proxy_to_realm' => 'Proxy-To-Realm',
+ 'aat_client_secondary_win' => 'AAT-Client-Secondary-WINS-NBNS',
+ 'aat_ip_tos_precedence' => 'AAT-IP-TOS-Precedence',
'acc_callback_num_valid' => 'Acc-Callback-Num-Valid',
- 'x_ascend_maximum_channel' => 'X-Ascend-Maximum-Channels',
+ 'nokia_ggsn_ip_address' => 'Nokia-GGSN-IP-Address',
'acc_access_community' => 'Acc-Access-Community',
- 'x_ascend_fr_direct_profi' => 'X-Ascend-FR-Direct-Profile',
+ 'ascend_multicast_rate_li' => 'Ascend-Multicast-Rate-Limit',
+ 'usr_default_dte_data_rat' => 'USR-Default-DTE-Data-Rate',
+ 'usr_rmmie_pwrlvl_nearech' => 'USR-RMMIE-PwrLvl-NearEcho-Canc',
'usr_send_name' => 'USR-Send-Name',
'usr_chassis_slot' => 'USR-Chassis-Slot',
'login_ip_host' => 'Login-IP-Host',
'ascend_netware_timeout' => 'Ascend-Netware-timeout',
+ 'bind_sub_user_at_context' => 'Bind-Sub-User-At-Context',
'vendor_specific' => 'Vendor-Specific',
- 'bind_sub_user_at_context' => 'Bind_Sub_User_At_Context',
'ascend_fr_direct_dlci' => 'Ascend-FR-Direct-DLCI',
- 'ascend_atm_fault_managem' => 'Ascend-ATM-Fault-Management',
'ascend_qos_upstream' => 'Ascend-QOS-Upstream',
- 'source_validation' => 'Source_Validation',
+ 'aat_user_mac_address' => 'AAT-User-MAC-Address',
+ 'source_validation' => 'Source-Validation',
'x_ascend_token_expiry' => 'X-Ascend-Token-Expiry',
+ 'altiga_ipsec_user_group_' => 'Altiga-IPSec-User-Group-Lock-G',
'ascend_dec_channel_count' => 'Ascend-Dec-Channel-Count',
+ 'assigned_ip_addrest' => 'Assigned_IP_Address',
'usr_local_framed_ip_addr' => 'USR-Local-Framed-IP-Addr',
'usr_service_option' => 'USR-Service-Option',
'usr_transmit_acc_map' => 'USR-Transmit-Acc-Map',
'ascend_fr_direct' => 'Ascend-FR-Direct',
+ 'usr_final_rx_link_data_r' => 'USR-Final-Rx-Link-Data-Rate',
'x_ascend_expect_callback' => 'X-Ascend-Expect-Callback',
+ 'x_ascend_disconnect_caus' => 'X-Ascend-Disconnect-Cause',
'acc_ml_damping_factor' => 'Acc-ML-Damping-Factor',
'framed_netmask' => 'Framed-Netmask',
'usr_connect_speed' => 'USR-Connect-Speed',
- 'ascend_client_primary_wi' => 'Ascend-Client-Primary-WINS',
+ 'x_ascend_home_agent_ip_a' => 'X-Ascend-Home-Agent-IP-Addr',
+ 'usr_disconnect_cause_ind' => 'USR-Disconnect-Cause-Indicator',
+ 'bg_span_dis' => 'BG-Span-Dis',
'cisco_multilink_id' => 'Cisco-Multilink-ID',
- 'bg_span_dis' => 'BG_Span_Dis',
+ 'tunnel_max_tunnels' => 'Tunnel-Max-Tunnels',
+ 'ascend_dsl_downstream_li' => 'Ascend-Dsl-Downstream-Limit',
'ascend_multilink_id' => 'Ascend-Multilink-ID',
- 'tunnel_max_tunnels' => 'Tunnel_Max_Tunnels',
+ 'altiga_ipsec_default_dom' => 'Altiga-IPSec-Default-Domain-G',
'ascend_dhcp_reply' => 'Ascend-DHCP-Reply',
+ 'login_ipv6_host' => 'Login-IPv6-Host',
'ascend_x25_cug' => 'Ascend-X25-Cug',
'shiva_network_protocols' => 'Shiva-Network-Protocols',
+ 'cvpn3000_ipsec_mode_conf' => 'CVPN3000-IPSec-Mode-Config',
+ 'extreme_netlogin_vlan' => 'Extreme-Netlogin-Vlan',
'ascend_ara_pw' => 'Ascend-Ara-PW',
- 'ip_host_addr' => 'Ip_Host_Addr',
+ 'tunnel_l2f_second_passwo' => 'Tunnel-L2F-Second-Password',
+ 'altiga_sep_card_assignme' => 'Altiga-SEP-Card-Assignment-G/U',
+ 'ip_host_addr' => 'Ip-Host-Addr',
'le_ip_gateway' => 'LE-IP-Gateway',
'usr_mobile_numbytes_txed' => 'USR-Mobile-NumBytes-Txed',
+ 'altiga_ipsec_allow_passw' => 'Altiga-IPSec-Allow-Passwd-Store-G/U',
+ 'itk_users_default_entry' => 'ITK-Users-Default-Entry',
+ 'quintum_h323_redirect_nu' => 'Quintum-h323-redirect-number',
'x_ascend_fr_t392' => 'X-Ascend-FR-T392',
+ 'acc_igmp_version' => 'Acc-Igmp-Version',
'cisco_pre_output_packets' => 'Cisco-Pre-Output-Packets',
- 'tunnel_group' => 'Tunnel_Group',
- 'bind_sub_password' => 'Bind_Sub_Password',
+ 'tunnel_group' => 'Tunnel-Group',
+ 'x_ascend_home_agent_udp_' => 'X-Ascend-Home-Agent-UDP-Port',
+ 'cvpn3000_tunneling_proto' => 'CVPN3000-Tunneling-Protocols',
+ 'usr_igmp_maximum_respons' => 'USR-IGMP-Maximum-Response-Time',
+ 'bind_sub_password' => 'Bind-Sub-Password',
'eap_message' => 'EAP-Message',
'exec_program' => 'Exec-Program',
- 'bg_path_cost' => 'BG_Path_Cost',
- 'auth_type' => 'Auth-Type',
+ 'cvpn3000_reqrd_client_fx' => 'CVPN3000-Reqrd-Client-Fw-Product-Code',
+ 'bg_path_cost' => 'BG-Path-Cost',
'usr_modem_training_time' => 'USR-Modem-Training-Time',
- 'ascend_cbcp_enable' => 'Ascend-CBCP-Enable',
+ 'auth_type' => 'Auth-Type',
+ 'itk_acct_serv_prot' => 'ITK-Acct-Serv-Prot',
'x_ascend_ipx_route' => 'X-Ascend-IPX-Route',
+ 'altiga_primary_dns_g' => 'Altiga-Primary-DNS-G',
+ 'ascend_cbcp_enable' => 'Ascend-CBCP-Enable',
+ 'ms_mppe_encryption_polic' => 'MS-MPPE-Encryption-Policy',
+ 'annex_unauthenticated_ti' => 'Annex-Unauthenticated-Time',
+ 'annex_begin_receive_line' => 'Annex-Begin-Receive-Line-Level',
+ 'ascend_atm_direct_profil' => 'Ascend-ATM-Direct-Profile',
+ 'redcreek_tunneled_dns_se' => 'RedCreek-Tunneled-DNS-Server',
'ascend_redirect_number' => 'Ascend-Redirect-Number',
'h323_credit_time' => 'h323-credit-time',
+ 'cvx_idle_limit' => 'CVX-Idle-Limit',
'ascend_appletalk_route' => 'Ascend-Appletalk-Route',
+ 'aat_ip_tos' => 'AAT-IP-TOS',
+ 'cvx_ppp_address' => 'CVX-PPP-Address',
+ 'aat_data_filter' => 'AAT-Data-Filter',
+ 'cvx_primary_dns' => 'CVX-Primary-DNS',
'shiva_link_protocol' => 'Shiva-Link-Protocol',
'x_ascend_fr_circuit_name' => 'X-Ascend-FR-Circuit-Name',
- 'client_id' => 'Client-Id',
'usr_appletalk' => 'USR-Appletalk',
- 'usr_mpip_tunnel_originat' => 'USR-MPIP-Tunnel-Originator',
+ 'client_id' => 'Client-Id',
+ 'tunnel_algorithn' => 'Tunnel_Algorithm',
+ 'aat_assign_ip_pool' => 'AAT-Assign-IP-Pool',
+ 'quintum_h323_incoming_co' => 'Quintum-h323-incoming-conf-id',
+ 'aat_atm_vpi' => 'AAT-ATM-VPI',
'annex_output_filter' => 'Annex-Output-Filter',
- 'pvc_circuit_padding' => 'PVC_Circuit_Padding',
- 'x_ascend_minimum_channel' => 'X-Ascend-Minimum-Channels',
+ 'pvc_circuit_padding' => 'PVC-Circuit-Padding',
+ 'usr_ipx_call_output_filt' => 'USR-IPX-Call-Output-Filter',
+ 'usr_rmmie_planned_discon' => 'USR-RMMIE-Planned-Disconnect',
+ 'session_error_msh' => 'Session_Error_Msg',
+ 'usr_rad_multicast_routin' => 'USR-Rad-Multicast-Routing-Ttl',
'h323_time_and_day' => 'h323-time-and-day',
- 'ascend_ipx_header_compre' => 'Ascend-IPX-Header-Compression',
+ 'cvpn3000_ipsec_backup_se' => 'CVPN3000-IPSec-Backup-Servers',
'termination_action' => 'Termination-Action',
- 'x_ascend_modem_portno' => 'X-Ascend-Modem-PortNo',
+ 'cvpn3000_ipsec_client_fx' => 'CVPN3000-IPSec-Client-Fw-Filter-Opt',
+ 'aat_client_primary_dnt' => 'AAT-Client-Primary-DNS',
'acct_tunnel_packets_lost' => 'Acct-Tunnel-Packets-Lost',
+ 'x_ascend_modem_portno' => 'X-Ascend-Modem-PortNo',
'framed_filter_id' => 'Framed-Filter-Id',
'usr_ccp_algorithm' => 'USR-CCP-Algorithm',
+ 'quintum_h323_preferred_l' => 'Quintum-h323-preferred-lang',
+ 'ascend_fr_link_status_dl' => 'Ascend-FR-Link-Status-DLCI',
'ascend_token_expiry' => 'Ascend-Token-Expiry',
- 'annex_secondary_nbns_ser' => 'Annex-Secondary-NBNS-Server',
- 'usr_et_bridge_call_outpu' => 'USR-ET-Bridge-Call-Output-Filte',
+ 'itk_auth_req_type' => 'ITK-Auth-Req-Type',
'acc_modem_error_protocol' => 'Acc-Modem-Error-Protocol',
'acc_request_type' => 'Acc-Request-Type',
+ 'usr_last_number_dialed_i' => 'USR-Last-Number-Dialed-In-DNIS',
'x_ascend_ipx_peer_mode' => 'X-Ascend-IPX-Peer-Mode',
'ascend_ppp_vj_slot_comp' => 'Ascend-PPP-VJ-Slot-Comp',
'cisco_presession_time' => 'Cisco-PreSession-Time',
'usr_chat_script_name' => 'USR-Chat-Script-Name',
+ 'tunnel_session_auti' => 'Tunnel_Session_Auth',
'ascend_fr_circuit_name' => 'Ascend-FR-Circuit-Name',
'ascend_expect_callback' => 'Ascend-Expect-Callback',
'framed_mtu' => 'Framed-MTU',
- 'ascend_port_redir_protoc' => 'Ascend-Port-Redir-Protocol',
'usr_pw_vpn_name' => 'USR-PW_VPN_Name',
+ 'nomadix_ip_upsell' => 'Nomadix-IP-Upsell',
'ascend_nas_port_format' => 'Ascend-NAS-Port-Format',
- 'shasta_vpn_name' => 'Shasta-VPN-Name',
'usr_dtr_true_timeout' => 'USR-DTR-True-Timeout',
- 'ascend_third_prompt' => 'Ascend-Third-Prompt',
+ 'shasta_vpn_name' => 'Shasta-VPN-Name',
'connect_rate' => 'Connect-Rate',
- 'usr_block_error_count_li' => 'USR-Block-Error-Count-Limit',
+ 'ascend_third_prompt' => 'Ascend-Third-Prompt',
+ 'cabletron_protocol_enabl' => 'Cabletron-Protocol-Enable',
+ 'annex_pre_input_octets' => 'Annex-Pre-Input-Octets',
+ 'cvx_modem_error_correcti' => 'CVX-Modem-Error-Correction',
+ 'cvx_ss7_session_id_type' => 'CVX-SS7-Session-ID-Type',
'called_station_id' => 'Called-Station-Id',
+ 'itk_ddi' => 'ITK-DDI',
'usr_pw_cutoff' => 'USR-PW_Cutoff',
'ascend_data_rate' => 'Ascend-Data-Rate',
+ 'acct_input_packets_65' => 'Acct_Input_Packets_64',
'x_ascend_ts_idle_mode' => 'X-Ascend-TS-Idle-Mode',
'ascend_x25_pad_prompt' => 'Ascend-X25-Pad-Prompt',
'x_ascend_dhcp_reply' => 'X-Ascend-DHCP-Reply',
'acc_nbns_server_pri' => 'Acc-Nbns-Server-Pri',
+ 'post_auth_type' => 'Post-Auth-Type',
'ascend_call_filter' => 'Ascend-Call-Filter',
'acc_tunnel_secret' => 'Acc-Tunnel-Secret',
- 'usr_simplified_v42bis_us' => 'USR-Simplified-V42bis-Usage',
- 'bind_int_context' => 'Bind_Int_Context',
+ 'colubris_avpair' => 'Colubris-AVPair',
+ 'bind_int_context' => 'Bind-Int-Context',
+ 'annex_logical_channel_nu' => 'Annex-Logical-Channel-Number',
'erx_virtual_router_name' => 'ERX-Virtual-Router-Name',
+ 'wispr_redirection_url' => 'WISPr-Redirection-URL',
+ 'bintec_ipextiftable' => 'BinTec-ipExtIfTable',
'crypt_password' => 'Crypt-Password',
'challenge_state' => 'Challenge-State',
- 'ascend_client_secondary_' => 'Ascend-Client-Secondary-DNS',
- 'strip_user_name' => 'Strip-User-Name',
+ 'x_ascend_pre_input_packe' => 'X-Ascend-Pre-Input-Packets',
+ 'altiga_ipsec_l2l_keepali' => 'Altiga-IPSec-L2L-Keepalives-G',
+ 'x_ascend_dhcp_maximum_le' => 'X-Ascend-DHCP-Maximum-Leases',
+ 'acc_dialout_auth_passwor' => 'Acc-Dialout-Auth-Password',
+ 'itk_ip_pool' => 'ITK-IP-Pool',
+ 'pvc_profile_namf' => 'PVC_Profile_Name',
'x_ascend_user_acct_host' => 'X-Ascend-User-Acct-Host',
- 'x_ascend_route_ip' => 'X-Ascend-Route-IP',
- 'x_ascend_assign_ip_clien' => 'X-Ascend-Assign-IP-Client',
+ 'strip_user_name' => 'Strip-User-Name',
+ 'itk_ppp_client_server_mo' => 'ITK-PPP-Client-Server-Mode',
'usr_mbi_ct_bchannel_used' => 'USR-Mbi_Ct_BChannel_Used',
+ 'x_ascend_route_ip' => 'X-Ascend-Route-IP',
+ 'ascend_seconds_of_histor' => 'Ascend-Seconds-Of-History',
+ 'cvx_data_rate' => 'CVX-Data-Rate',
'ascend_x25_profile_name' => 'Ascend-X25-Profile-Name',
+ 'itk_ftp_auth_ip' => 'ITK-Ftp-Auth-IP',
+ 'cisco_control_info' => 'Cisco-Control-Info',
+ 'cvpn3000_secondary_wins' => 'CVPN3000-Secondary-WINS',
'usr_call_type' => 'USR-Call-Type',
'x_ascend_user_acct_base' => 'X-Ascend-User-Acct-Base',
+ 'acct_mcast_in_packett' => 'Acct_Mcast_In_Packets',
+ 'ns_vsys_name' => 'NS-VSYS-Name',
'acct_output_gigawords' => 'Acct-Output-Gigawords',
- 'usr_rmmie_firmware_build' => 'USR-RMMIE-Firmware-Build-Date',
- 'ascend_fr_link_status_dl' => 'Ascend-FR-Link-Status-DLCI',
+ 'bind_typf' => 'Bind_Type',
+ 'bintec_ipqostable' => 'BinTec-ipQoSTable',
+ 'bintec_ipxstaticservtabl' => 'BinTec-ipxStaticServTable',
+ 'cvpn3000_l2tp_mppc_compr' => 'CVPN3000-L2TP-MPPC-Compression',
'login_lat_port' => 'Login-LAT-Port',
'usr_call_arrival_in_gmt' => 'USR-Call-Arrival-in-GMT',
- 'acct_mcast_in_octets' => 'Acct_Mcast_In_Octets',
+ 'acct_mcast_in_octets' => 'Acct-Mcast-In-Octets',
'erx_sa_validate' => 'ERX-Sa-Validate',
'ascend_service_type' => 'Ascend-Service-Type',
- 'ascend_x25_nui_password_' => 'Ascend-X25-Nui-Password-Prompt',
'usr_pw_vpn_gateway' => 'USR-PW_VPN_Gateway',
- 'ascend_fr_dce_n392' => 'Ascend-FR-DCE-N392',
'acc_ip_compression' => 'Acc-Ip-Compression',
- 'lac_real_port_type' => 'LAC_Real_Port_Type',
- 'ascend_if_netmask' => 'Ascend-IF-Netmask',
+ 'ascend_fr_dce_n392' => 'Ascend-FR-DCE-N392',
+ 'bintec_ipxcirctable' => 'BinTec-ipxCircTable',
+ 'lac_real_port_type' => 'LAC-Real-Port-Type',
+ 'ascend_client_primary_dn' => 'Ascend-Client-Primary-DNS',
'acct_session_start_time' => 'Acct-Session-Start-Time',
+ 'ascend_if_netmask' => 'Ascend-IF-Netmask',
'ms_chap_nt_enc_pw' => 'MS-CHAP-NT-Enc-PW',
- 'ascend_port_redir_portnu' => 'Ascend-Port-Redir-Portnum',
- 'mcast_maxgroups' => 'Mcast_MaxGroups',
- 'x_ascend_home_agent_ip_a' => 'X-Ascend-Home-Agent-IP-Addr',
+ 'ms_mppe_encryption_types' => 'MS-MPPE-Encryption-Types',
+ 'cisco_fax_process_abort_' => 'Cisco-Fax-Process-Abort-Flag',
+ 'mcast_maxgroups' => 'Mcast-MaxGroups',
+ 'annex_end_receive_line_l' => 'Annex-End-Receive-Line-Level',
+ 'usr_ipx_call_input_filte' => 'USR-IPX-Call-Input-Filter',
+ 'usr_back_channel_data_ra' => 'USR-Back-Channel-Data-Rate',
'ascend_cache_time' => 'Ascend-Cache-Time',
'x_ascend_data_svc' => 'X-Ascend-Data-Svc',
- 'erx_tunnel_virtual_route' => 'ERX-Tunnel-Virtual-Router',
'usr_re_chap_timeout' => 'USR-Re-Chap-Timeout',
+ 'bintec_bibodialtable' => 'BinTec-biboDialTable',
+ 'annex_connect_progress' => 'Annex-Connect-Progress',
'x_ascend_ppp_vj_1172' => 'X-Ascend-PPP-VJ-1172',
'usr_igmp_routing' => 'USR-IGMP-Routing',
+ 'x_ascend_ip_pool_definit' => 'X-Ascend-IP-Pool-Definition',
'h323_prompt_id' => 'h323-prompt-id',
+ 'foundry_command_string' => 'Foundry-Command-String',
'le_terminate_detail' => 'LE-Terminate-Detail',
+ 'cvpn3000_pptp_encryption' => 'CVPN3000-PPTP-Encryption',
+ 'quintum_h323_disconnect_' => 'Quintum-h323-disconnect-time',
'acc_ml_clear_threshold' => 'Acc-ML-Clear-Threshold',
'x_ascend_ip_direct' => 'X-Ascend-IP-Direct',
- 'nas_port' => 'NAS-Port',
- 'x_ascend_data_rate' => 'X-Ascend-Data-Rate',
'usr_ip_call_input_filter' => 'USR-IP-Call-Input-Filter',
+ 'x_ascend_data_rate' => 'X-Ascend-Data-Rate',
+ 'nas_port' => 'NAS-Port',
+ 'ascend_client_secondary_' => 'Ascend-Client-Secondary-WINS',
'ascend_auth_type' => 'Ascend-Auth-Type',
'x_ascend_preempt_limit' => 'X-Ascend-Preempt-Limit',
+ 'cvx_xmit_rate' => 'CVX-Xmit-Rate',
+ 'annex_transmitted_packet' => 'Annex-Transmitted-Packets',
'h323_credit_amount' => 'h323-credit-amount',
'usr_reply_script1' => 'USR-Reply-Script1',
- 'usr_et_bridge_input_filt' => 'USR-ET-Bridge-Input-Filter',
'current_time' => 'Current-Time',
'cisco_xmit_rate' => 'Cisco-Xmit-Rate',
- 'ascend_authen_alias' => 'Ascend-Authen-Alias',
'x_ascend_session_svr_key' => 'X-Ascend-Session-Svr-Key',
+ 'ascend_authen_alias' => 'Ascend-Authen-Alias',
+ 'erx_redirect_vr_name' => 'ERX-Redirect-VR-Name',
+ 'module_success_message' => 'Module-Success-Message',
'acc_dialout_auth_mode' => 'Acc-Dialout-Auth-Mode',
+ 'bind_auth_contexu' => 'Bind_Auth_Context',
+ 'x_ascend_minimum_channel' => 'X-Ascend-Minimum-Channels',
'usr_event_date_time' => 'USR-Event-Date-Time',
'x_ascend_ipx_node_addr' => 'X-Ascend-IPX-Node-Addr',
- 'ascend_primary_home_agen' => 'Ascend-Primary-Home-Agent',
+ 'cvpn3000_ipsec_over_udp' => 'CVPN3000-IPSec-Over-UDP',
'x_ascend_user_acct_time' => 'X-Ascend-User-Acct-Time',
- 'usr_at_call_output_filte' => 'USR-AT-Call-Output-Filter',
+ 'cisco_email_server_ack_f' => 'Cisco-Email-Server-Ack-Flag',
+ 'telebit_activate_command' => 'Telebit-Activate-Command',
'acc_output_errors' => 'Acc-Output-Errors',
- 'usr_ipx_rip_output_filte' => 'USR-IPX-RIP-Output-Filter',
+ 'juniper_allow_configurat' => 'Juniper-Allow-Configuration',
+ 'bind_l2tp_tunnel_name' => 'Bind-L2TP-Tunnel-Name',
'x_ascend_pri_number_type' => 'X-Ascend-PRI-Number-Type',
- 'bind_l2tp_tunnel_name' => 'Bind_L2TP_Tunnel_Name',
- 'replicate_to_realm' => 'Replicate-To-Realm',
+ 'bintec_biboppptable' => 'BinTec-biboPPPTable',
+ 'le_ipsec_outsource_profi' => 'LE-IPSec-Outsource-Profile',
'usr_at_zip_input_filter' => 'USR-AT-Zip-Input-Filter',
+ 'replicate_to_realm' => 'Replicate-To-Realm',
'annex_mrru' => 'Annex-MRRU',
'event_timestamp' => 'Event-Timestamp',
+ 'nokia_sgsn_ip_address' => 'Nokia-SGSN-IP-Address',
'ascend_pre_input_packets' => 'Ascend-Pre-Input-Packets',
+ 'cvpn5000_client_assigned' => 'CVPN5000-Client-Assigned-IP',
+ 'tunnel_dnit' => 'Tunnel_DNIS',
'h323_call_origin' => 'h323-call-origin',
'x_ascend_fr_type' => 'X-Ascend-FR-Type',
+ 'itk_provider_id' => 'ITK-Provider-Id',
+ 'cvx_ppp_log_mask' => 'CVX-PPP-Log-Mask',
'x_ascend_token_idle' => 'X-Ascend-Token-Idle',
+ 'usr_rmmie_pwrlvl_xmit_lv' => 'USR-RMMIE-PwrLvl-Xmit-Lvl',
'usr_igmp_query_interval' => 'USR-IGMP-Query-Interval',
+ 'quintum_h323_billing_mod' => 'Quintum-h323-billing-model',
'ascend_atm_vci' => 'Ascend-ATM-Vci',
'usr_port_tap_output' => 'USR-Port-Tap-Output',
'session' => 'Session',
+ 'itk_welcome_message' => 'ITK-Welcome-Message',
+ 'cvpn3000_ike_keep_alives' => 'CVPN3000-IKE-Keep-Alives',
'ascend_uu_info' => 'Ascend-UU-Info',
- 'ms_mppe_recv_key' => 'MS-MPPE-Recv-Key',
+ 'usr_et_bridge_call_outpu' => 'USR-ET-Bridge-Call-Output-Filte',
'usr_secondary_dns_server' => 'USR-Secondary_DNS_Server',
- 'x_ascend_tunneling_proto' => 'X-Ascend-Tunneling-Protocol',
+ 'ms_mppe_recv_key' => 'MS-MPPE-Recv-Key',
+ 'bintec_ripcirctable' => 'BinTec-ripCircTable',
'acc_dial_port_index' => 'Acc-Dial-Port-Index',
'cisco_nas_port' => 'Cisco-NAS-Port',
+ 'itk_username' => 'ITK-Username',
'usr_send_script1' => 'USR-Send-Script1',
+ 'cvpn3000_ipsec_ike_peer_' => 'CVPN3000-IPSec-IKE-Peer-ID-Check',
+ 'ascend_dsl_upstream_limi' => 'Ascend-Dsl-Upstream-Limit',
+ 'x_ascend_dec_channel_cou' => 'X-Ascend-Dec-Channel-Count',
'usr_tunnel_security' => 'USR-Tunnel-Security',
'arap_security' => 'ARAP-Security',
'tunnel_preference' => 'Tunnel-Preference',
+ 'cisco_port_used' => 'Cisco-Port-Used',
'usr_reply_script4' => 'USR-Reply-Script4',
- 'h323_currency_type' => 'h323-currency-type',
+ 'cvpn5000_client_real_ip' => 'CVPN5000-Client-Real-IP',
'usr_rmmie_status' => 'USR-RMMIE-Status',
- 'ascend_shared_profile_en' => 'Ascend-Shared-Profile-Enable',
- 'annex_syslog_tap' => 'Annex-Syslog-Tap',
'usr_send_script4' => 'USR-Send-Script4',
+ 'quintum_h323_connect_tim' => 'Quintum-h323-connect-time',
+ 'annex_syslog_tap' => 'Annex-Syslog-Tap',
+ 'redcreek_tunneled_hostna' => 'RedCreek-Tunneled-HostName',
'acc_clearing_location' => 'Acc-Clearing-Location',
+ 'ascend_access_intercept_' => 'Ascend-Access-Intercept-LEA',
'annex_disconnect_reason' => 'Annex-Disconnect-Reason',
- 'x_ascend_dhcp_maximum_le' => 'X-Ascend-DHCP-Maximum-Leases',
'usr_at_input_filter' => 'USR-AT-Input-Filter',
'usr_auth_mode' => 'USR-Auth-Mode',
- 'shiva_session_id' => 'Shiva-Session-Id',
'usr_expected_voltage' => 'USR-Expected-Voltage',
+ 'shiva_session_id' => 'Shiva-Session-Id',
+ 'annex_maximum_call_durat' => 'Annex-Maximum-Call-Duration',
+ 'usr_block_error_count_li' => 'USR-Block-Error-Count-Limit',
'ascend_owner_ip_addr' => 'Ascend-Owner-IP-Addr',
- 'ascend_atm_direct_profil' => 'Ascend-ATM-Direct-Profile',
+ 'bind_tun_contexu' => 'Bind_Tun_Context',
'usr_pw_usr_ofilter_ipx' => 'USR-PW_USR_OFilter_IPX',
'framed_routing' => 'Framed-Routing',
- 'pam_auth' => 'Pam-Auth',
+ 'annex_primary_nbns_serve' => 'Annex-Primary-NBNS-Server',
'usr_interface_index' => 'USR-Interface-Index',
- 'x_ascend_transit_number' => 'X-Ascend-Transit-Number',
+ 'pam_auth' => 'Pam-Auth',
'usr_end_time' => 'USR-End-Time',
+ 'rate_limit_bursu' => 'Rate_Limit_Burst',
+ 'nomadix_expiration' => 'Nomadix-Expiration',
+ 'x_ascend_transit_number' => 'X-Ascend-Transit-Number',
+ 'itk_usergroup' => 'ITK-Usergroup',
'x_ascend_assign_ip_pool' => 'X-Ascend-Assign-IP-Pool',
+ 'annex_secondary_nbns_ser' => 'Annex-Secondary-NBNS-Server',
+ 'bind_dot1q_vlan_tag_id' => 'Bind-Dot1q-Vlan-Tag-Id',
'ms_secondary_nbns_server' => 'MS-Secondary-NBNS-Server',
- 'bind_dot1q_vlan_tag_id' => 'Bind_Dot1q_Vlan_Tag_Id',
+ 'tunnel_retransmit' => 'Tunnel-Retransmit',
'acct_tunnel_connection' => 'Acct-Tunnel-Connection',
- 'tunnel_retransmit' => 'Tunnel_Retransmit',
'x_ascend_backup' => 'X-Ascend-Backup',
+ 'xedia_ppp_echo_interval' => 'Xedia-PPP-Echo-Interval',
'usr_bearer_capabilities' => 'USR-Bearer-Capabilities',
- 'ascend_calling_id_type_o' => 'Ascend-Calling-Id-Type-Of-Num',
'shiva_acct_serv_switch' => 'Shiva-Acct-Serv-Switch',
- 'ascend_h323_conference_i' => 'Ascend-H323-Conference-Id',
'acct_authentic' => 'Acct-Authentic',
+ 'le_nat_other_session_tim' => 'LE-NAT-Other-Session-Timeout',
+ 'cvpn3000_ipsec_banner2' => 'CVPN3000-IPSec-Banner2',
'x_ascend_force_56' => 'X-Ascend-Force-56',
'framed_appletalk_network' => 'Framed-AppleTalk-Network',
'reply_message' => 'Reply-Message',
- 'annex_addr_resolution_pr' => 'Annex-Addr-Resolution-Protocol',
'class' => 'Class',
'h323_conf_id' => 'h323-conf-id',
+ 'quintum_h323_disconnecta' => 'Quintum-h323-disconnect-cause',
+ 'itk_filter_rule' => 'ITK-Filter-Rule',
+ 'wispr_bandwidth_max_up' => 'WISPr-Bandwidth-Max-Up',
+ 'usr_appletalk_network_ra' => 'USR-Appletalk-Network-Range',
'ascend_cbcp_delay' => 'Ascend-CBCP-Delay',
+ 'usr_dte_ring_no_answer_l' => 'USR-DTE-Ring-No-Answer-Limit',
+ 'pre_acct_type' => 'Pre-Acct-Type',
+ 'usr_local_ip_address' => 'USR-Local-IP-Address',
'ascend_dropped_octets' => 'Ascend-Dropped-Octets',
'ascend_h323_dialed_time' => 'Ascend-H323-Dialed-Time',
- 'usr_local_ip_address' => 'USR-Local-IP-Address',
+ 'cisco_email_server_addre' => 'Cisco-Email-Server-Address',
'ascend_x25_x121_address' => 'Ascend-X25-X121-Address',
- 'ascend_destination_nas_p' => 'Ascend-Destination-Nas-Port',
- 'annex_local_ip_address' => 'Annex-Local-IP-Address',
+ 'cvx_multicast_client' => 'CVX-Multicast-Client',
+ 'wispr_bandwidth_min_up' => 'WISPr-Bandwidth-Min-Up',
'usr_at_output_filter' => 'USR-AT-Output-Filter',
+ 'annex_local_ip_address' => 'Annex-Local-IP-Address',
'cisco_ip_pool_definition' => 'Cisco-IP-Pool-Definition',
+ 'cisco_gateway_id' => 'Cisco-Gateway-Id',
+ 'itk_password_prompt' => 'ITK-Password-Prompt',
'annex_domain_name' => 'Annex-Domain-Name',
+ 'foundry_command_exceptio' => 'Foundry-Command-Exception-Flag',
'ascend_preempt_limit' => 'Ascend-Preempt-Limit',
+ 'erx_minimum_bps' => 'ERX-Minimum-BPS',
+ 'aat_mcast_client' => 'AAT-MCast-Client',
+ 'ascend_atm_fault_managem' => 'Ascend-ATM-Fault-Management',
'ascend_event_type' => 'Ascend-Event-Type',
- 'x_ascend_pre_input_octet' => 'X-Ascend-Pre-Input-Octets',
'exec_program_wait' => 'Exec-Program-Wait',
-
- #NOMENT
- 'nomadix_ip_upsell' => 'Nomadix-IP-Upsell',
+ 'framed_interface_id' => 'Framed-Interface-Id',
#NETC.NET.AU (RADIATOR?)
'authentication_type' => 'Authentication-Type',
diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm
index 524e55086..a154f3f85 100644
--- a/FS/FS/svc_Common.pm
+++ b/FS/FS/svc_Common.pm
@@ -49,8 +49,10 @@ sub virtual_fields {
if ($self->svcpart) { # Case 1
$svcpart = $self->svcpart;
- } elsif (my $cust_svc = $self->cust_svc) { # Case 2
- $svcpart = $cust_svc->svcpart;
+ } elsif ( $self->svcnum
+ && qsearchs('cust_svc',{'svcnum'=>$self->svcnum} )
+ ) { #Case 2
+ $svcpart = $self->cust_svc->svcpart;
} else { # Case 3
$svcpart = '';
}
@@ -80,7 +82,7 @@ sub check {
$self->SUPER::check;
}
-=item insert [ JOBNUM_ARRAYREF ]
+=item insert [ JOBNUM_ARRAYREF [ OBJECTS_ARRAYREF ] ]
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
@@ -91,11 +93,16 @@ defined. An FS::cust_svc record will be created and inserted.
If an arrayref is passed as parameter, the B<jobnum>s of any export jobs will
be added to the array.
+If an arrayref of FS::tablename objects (for example, FS::acct_snarf objects)
+is passed as the optional second parameter, they will have their svcnum fields
+set and will be inserted after this record, but before any exports are run.
+
=cut
sub insert {
my $self = shift;
local $FS::queue::jobnums = shift if @_;
+ my $objects = scalar(@_) ? shift : [];
my $error;
local $SIG{HUP} = 'IGNORE';
@@ -113,10 +120,12 @@ sub insert {
return $error if $error;
my $svcnum = $self->svcnum;
- my $cust_svc;
- unless ( $svcnum ) {
+ my $cust_svc = $svcnum ? qsearchs('cust_svc',{'svcnum'=>$self->svcnum}) : '';
+ #unless ( $svcnum ) {
+ if ( !$svcnum or !$cust_svc ) {
$cust_svc = new FS::cust_svc ( {
#hua?# 'svcnum' => $svcnum,
+ 'svcnum' => $self->svcnum,
'pkgnum' => $self->pkgnum,
'svcpart' => $self->svcpart,
} );
@@ -127,7 +136,7 @@ sub insert {
}
$svcnum = $self->svcnum($cust_svc->svcnum);
} else {
- $cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
+ #$cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
unless ( $cust_svc ) {
$dbh->rollback if $oldAutoCommit;
return "no cust_svc record found for svcnum ". $self->svcnum;
@@ -142,6 +151,15 @@ sub insert {
return $error;
}
+ foreach my $object ( @$objects ) {
+ $object->svcnum($self->svcnum);
+ $error = $object->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
#new-style exports!
unless ( $noexport_hack ) {
foreach my $part_export ( $self->cust_svc->part_svc->part_export ) {
@@ -294,7 +312,7 @@ sub setx {
#get part_svc
my $svcpart;
- if ( $self->svcnum ) {
+ if ( $self->svcnum && qsearchs('cust_svc', {'svcnum'=>$self->svcnum}) ) {
my $cust_svc = $self->cust_svc;
return "Unknown svcnum" unless $cust_svc;
$svcpart = $cust_svc->svcpart;
@@ -412,11 +430,31 @@ methods. Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
sub cancel { ''; }
-=back
+=item clone_suspended
+
+Constructor used by FS::part_export::_export_suspend fallback. Stub returning
+same object for svc_ classes which don't implement a suspension fallback
+(everything except svc_acct at the moment). Document better.
-=head1 VERSION
+=cut
+
+sub clone_suspended {
+ shift;
+}
+
+=item clone_kludge_unsuspend
+
+Constructor used by FS::part_export::_export_unsuspend fallback. Stub returning
+same object for svc_ classes which don't implement a suspension fallback
+(everything except svc_acct at the moment). Document better.
-$Id: svc_Common.pm,v 1.13 2003-08-05 00:20:47 khoff Exp $
+=cut
+
+sub clone_kludge_unsuspend {
+ shift;
+}
+
+=back
=head1 BUGS
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index 0ee7a7286..32d87202e 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -16,7 +16,7 @@ use Carp;
use Fcntl qw(:flock);
use FS::UID qw( datasrc );
use FS::Conf;
-use FS::Record qw( qsearch qsearchs fields dbh );
+use FS::Record qw( qsearch qsearchs fields dbh dbdef );
use FS::svc_Common;
use FS::cust_svc;
use FS::part_svc;
@@ -188,10 +188,16 @@ The additional field I<usergroup> can optionally be defined; if so it should
contain an arrayref of group names. See L<FS::radius_usergroup>. (used in
sqlradius export only)
+The additional field I<child_objects> can optionally be defined; if so it
+should contain an arrayref of FS::tablename objects. They will have their
+svcnum fields set and will be inserted after this record, but before any
+exports are run.
+
(TODOC: L<FS::queue> and L<freeside-queued>)
(TODOC: new exports!)
+
=cut
sub insert {
@@ -220,7 +226,7 @@ sub insert {
# 'domsvc' => $self->domsvc,
# } );
- if ( $self->svcnum ) {
+ if ( $self->svcnum && qsearchs('cust_svc',{'svcnum'=>$self->svcnum}) ) {
my $cust_svc = qsearchs('cust_svc',{'svcnum'=>$self->svcnum});
unless ( $cust_svc ) {
$dbh->rollback if $oldAutoCommit;
@@ -319,7 +325,7 @@ sub insert {
#see? i told you it was more complicated
my @jobnums;
- $error = $self->SUPER::insert(\@jobnums);
+ $error = $self->SUPER::insert(\@jobnums, $self->child_objects || [] );
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -421,6 +427,8 @@ The corresponding FS::cust_svc record will be deleted as well.
sub delete {
my $self = shift;
+ return "can't delete system account" if $self->_check_system;
+
return "Can't delete an account which is a (svc_forward) source!"
if qsearch( 'svc_forward', { 'srcsvc' => $self->svcnum } );
@@ -509,6 +517,8 @@ sub replace {
my $error;
warn "$me replacing $old with $new\n" if $DEBUG;
+ return "can't modify system account" if $old->_check_system;
+
return "Username in use"
if $old->username ne $new->username &&
qsearchs( 'svc_acct', { 'username' => $new->username,
@@ -599,39 +609,26 @@ sub replace {
=item suspend
-Suspends this account by prefixing *SUSPENDED* to the password. If there is an
-error, returns the error, otherwise returns false.
+Suspends this account by calling export-specific suspend hooks. If there is
+an error, returns the error, otherwise returns false.
Called by the suspend method of FS::cust_pkg (see L<FS::cust_pkg>).
-Calls any export-specific suspend hooks.
-
=cut
sub suspend {
my $self = shift;
- my %hash = $self->hash;
- unless ( $hash{_password} =~ /^\*SUSPENDED\* /
- || $hash{_password} eq '*'
- ) {
- $hash{_password} = '*SUSPENDED* '.$hash{_password};
- my $new = new FS::svc_acct ( \%hash );
- my $error = $new->replace($self);
- return $error if $error;
- }
-
+ return "can't suspend system account" if $self->_check_system;
$self->SUPER::suspend;
}
=item unsuspend
-Unsuspends this account by removing *SUSPENDED* from the password. If there is
-an error, returns the error, otherwise returns false.
+Unsuspends this account by by calling export-specific suspend hooks. If there
+is an error, returns the error, otherwise returns false.
Called by the unsuspend method of FS::cust_pkg (see L<FS::cust_pkg>).
-Calls any export-specific unsuspend hooks.
-
=cut
sub unsuspend {
@@ -784,7 +781,7 @@ sub check {
or return "Illegal finger: ". $self->getfield('finger');
$self->setfield('finger', $1);
- $recref->{quota} =~ /^(\d*)$/ or return "Illegal quota";
+ $recref->{quota} =~ /^(\w*)$/ or return "Illegal quota";
$recref->{quota} = $1;
unless ( $part_svc->part_svc_column('slipip')->columnflag eq 'F' ) {
@@ -819,10 +816,12 @@ sub check {
#$recref->{password} = $1.
# crypt($3,$saltset[int(rand(64))].$saltset[int(rand(64))]
#;
- } elsif ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([\w\.\/\$\;\+]{13,34})$/ ) {
+ } elsif ( $recref->{_password} =~ /^((\*SUSPENDED\* )?)([\w\.\/\$\;\+]{13,60})$/ ) {
$recref->{_password} = $1.$3;
} elsif ( $recref->{_password} eq '*' ) {
$recref->{_password} = '*';
+ } elsif ( $recref->{_password} eq '!' ) {
+ $recref->{_password} = '!';
} elsif ( $recref->{_password} eq '!!' ) {
$recref->{_password} = '!!';
} else {
@@ -835,6 +834,17 @@ sub check {
$self->SUPER::check;
}
+=item _check_system
+
+=cut
+
+sub _check_system {
+ my $self = shift;
+ scalar( grep { $self->username eq $_ || $self->email eq $_ }
+ $conf->config('system_usernames')
+ );
+}
+
=item radius
Depriciated, use radius_reply instead.
@@ -947,6 +957,22 @@ sub email {
$self->username. '@'. $self->domain;
}
+=item acct_snarf
+
+Returns an array of FS::acct_snarf records associated with the account.
+If the acct_snarf table does not exist or there are no associated records,
+an empty list is returned
+
+=cut
+
+sub acct_snarf {
+ my $self = shift;
+ return () unless dbdef->table('acct_snarf');
+ eval "use FS::acct_snarf;";
+ die $@ if $@;
+ qsearch('acct_snarf', { 'svcnum' => $self->svcnum } );
+}
+
=item seconds_since TIMESTAMP
Returns the number of seconds this account has been online since TIMESTAMP,
@@ -1005,6 +1031,18 @@ sub attribute_since_sqlradacct {
$self->cust_svc->attribute_since_sqlradacct(@_);
}
+=item get_session_history_sqlradacct TIMESTAMP_START TIMESTAMP_END
+
+Returns an array of hash references of this customers login history for the
+given time range. (document this better)
+
+=cut
+
+sub get_session_history_sqlradacct {
+ my $self = shift;
+ $self->cust_svc->get_session_history_sqlradacct(@_);
+}
+
=item radius_groups
Returns all RADIUS groups for this account (see L<FS::radius_usergroup>).
@@ -1023,6 +1061,34 @@ sub radius_groups {
}
}
+=item clone_suspended
+
+Constructor used by FS::part_export::_export_suspend fallback. Document
+better.
+
+=cut
+
+sub clone_suspended {
+ my $self = shift;
+ my %hash = $self->hash;
+ $hash{_password} = join('',map($pw_set[ int(rand $#pw_set) ], (0..7) ) );
+ new FS::svc_acct \%hash;
+}
+
+=item clone_kludge_unsuspend
+
+Constructor used by FS::part_export::_export_unsuspend fallback. Document
+better.
+
+=cut
+
+sub clone_kludge_unsuspend {
+ my $self = shift;
+ my %hash = $self->hash;
+ $hash{_password} = '';
+ new FS::svc_acct \%hash;
+}
+
=back
=head1 SUBROUTINES
diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm
index ff0fa2f61..10d5d8f5c 100644
--- a/FS/FS/svc_domain.pm
+++ b/FS/FS/svc_domain.pm
@@ -342,9 +342,8 @@ sub check {
return "Unknown catchall" unless $svc_acct;
}
- my $error = $self->ut_textn('purpose')
- or $self->SUPER::check;
- return $error if $error;
+ $self->ut_textn('purpose')
+ or $self->SUPER::check;
}
diff --git a/FS/FS/svc_external.pm b/FS/FS/svc_external.pm
new file mode 100644
index 000000000..fe4ea1d67
--- /dev/null
+++ b/FS/FS/svc_external.pm
@@ -0,0 +1,174 @@
+package FS::svc_external;
+
+use strict;
+use vars qw(@ISA); # $conf
+use FS::UID;
+#use FS::Record qw( qsearch qsearchs dbh);
+use FS::svc_Common;
+
+@ISA = qw( FS::svc_Common );
+
+#FS::UID::install_callback( sub {
+# $conf = new FS::Conf;
+#};
+
+=head1 NAME
+
+FS::svc_external - Object methods for svc_external records
+
+=head1 SYNOPSIS
+
+ use FS::svc_external;
+
+ $record = new FS::svc_external \%hash;
+ $record = new FS::svc_external { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+ $error = $record->suspend;
+
+ $error = $record->unsuspend;
+
+ $error = $record->cancel;
+
+=head1 DESCRIPTION
+
+An FS::svc_external object represents a externally tracked service.
+FS::svc_external inherits from FS::svc_Common. The following fields are
+currently supported:
+
+=over 4
+
+=item svcnum - primary key
+
+=item id - unique number of external record
+
+=item title - for invoice line items
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new external service. To add the external service to the database,
+see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to. You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+sub table { 'svc_external'; }
+
+=item insert
+
+Adds this external service to the database. If there is an error, returns the
+error, otherwise returns false.
+
+The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
+defined. An FS::cust_svc record will be created and inserted.
+
+=cut
+
+sub insert {
+ my $self = shift;
+ my $error;
+
+ $error = $self->SUPER::insert;
+ return $error if $error;
+
+ '';
+}
+
+=item delete
+
+Delete this record from the database.
+
+=cut
+
+sub delete {
+ my $self = shift;
+ my $error;
+
+ $error = $self->SUPER::delete;
+ return $error if $error;
+
+ '';
+}
+
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+=cut
+
+sub replace {
+ my ( $new, $old ) = ( shift, shift );
+ my $error;
+
+ $error = $new->SUPER::replace($old);
+ return $error if $error;
+
+ '';
+}
+
+=item suspend
+
+Called by the suspend method of FS::cust_pkg (see L<FS::cust_pkg>).
+
+=item unsuspend
+
+Called by the unsuspend method of FS::cust_pkg (see L<FS::cust_pkg>).
+
+=item cancel
+
+Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
+
+=item check
+
+Checks all fields to make sure this is a valid external service. If there is
+an error, returns the error, otherwise returns false. Called by the insert
+and repalce methods.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $x = $self->setfixed;
+ return $x unless ref($x);
+ my $part_svc = $x;
+
+ my $error =
+ $self->ut_numbern('svcnum')
+ || $self->ut_number('id')
+ || $self->ut_textn('title')
+ ;
+
+ $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::svc_Common>, L<FS::Record>, L<FS::cust_svc>, L<FS::part_svc>,
+L<FS::cust_pkg>, schema.html from the base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/svc_forward.pm b/FS/FS/svc_forward.pm
index 7a121b835..b9e8ff8f7 100644
--- a/FS/FS/svc_forward.pm
+++ b/FS/FS/svc_forward.pm
@@ -47,9 +47,11 @@ inherits from FS::Record. The following fields are currently supported:
=item srcsvc - svcnum of the source of the forward (see L<FS::svc_acct>)
+=item src - literal source (username or full email address)
+
=item dstsvc - svcnum of the destination of the forward (see L<FS::svc_acct>)
-=item dst - foreign destination (email address) - forward not local to freeside
+=item dst - literal destination (username or full email address)
=back
@@ -214,12 +216,19 @@ sub check {
#my $part_svc = $x;
my $error = $self->ut_numbern('svcnum')
- || $self->ut_number('srcsvc')
+ || $self->ut_numbern('srcsvc')
|| $self->ut_numbern('dstsvc')
;
return $error if $error;
- return "Unknown srcsvc" unless $self->srcsvc_acct;
+ return "Both srcsvc and src were defined; only one can be specified"
+ if $self->srcsvc && $self->src;
+
+ return "one of srcsvc or src is required"
+ unless $self->srcsvc || $self->src;
+
+ return "Unknown srcsvc: ". $self->srcsvc
+ unless ! $self->srcsvc || $self->srcsvc_acct;
return "Both dstsvc and dst were defined; only one can be specified"
if $self->dstsvc && $self->dst;
@@ -227,16 +236,24 @@ sub check {
return "one of dstsvc or dst is required"
unless $self->dstsvc || $self->dst;
- #return "Unknown dstsvc: $dstsvc" unless $self->dstsvc_acct || ! $self->dstsvc;
- return "Unknown dstsvc"
- unless qsearchs('svc_acct', { 'svcnum' => $self->dstsvc } )
- || ! $self->dstsvc;
+ return "Unknown dstsvc: ". $self->dstsvc
+ unless ! $self->dstsvc || $self->dstsvc_acct;
+ #return "Unknown dstsvc"
+ # unless qsearchs('svc_acct', { 'svcnum' => $self->dstsvc } )
+ # || ! $self->dstsvc;
+ if ( $self->src ) {
+ $self->src =~ /^([\w\.\-\&]*)(\@([\w\-]+\.)+\w+)?$/
+ or return "Illegal src: ". $self->dst;
+ $self->src("$1$2");
+ } else {
+ $self->src('');
+ }
if ( $self->dst ) {
- $self->dst =~ /^([\w\.\-]+)\@(([\w\-]+\.)+\w+)$/
+ $self->dst =~ /^([\w\.\-\&]*)(\@([\w\-]+\.)+\w+)?$/
or return "Illegal dst: ". $self->dst;
- $self->dst("$1\@$2");
+ $self->dst("$1$2");
} else {
$self->dst('');
}
@@ -246,7 +263,8 @@ sub check {
=item srcsvc_acct
-Returns the FS::svc_acct object referenced by the srcsvc column.
+Returns the FS::svc_acct object referenced by the srcsvc column, or false for
+literally specified forwards.
=cut
@@ -258,7 +276,7 @@ sub srcsvc_acct {
=item dstsvc_acct
Returns the FS::svc_acct object referenced by the srcsvc column, or false for
-forwards not local to freeside.
+literally specified forwards.
=cut
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 0fbbf5cb5..3cbf0e91f 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -19,7 +19,6 @@ bin/freeside-email
bin/freeside-expiration-alerter
bin/freeside-queued
bin/freeside-radgroup
-bin/freeside-receivables-report
bin/freeside-reexport
bin/freeside-selfservice-server
bin/freeside-setinvoice
@@ -45,6 +44,7 @@ FS/UI/Gtk.pm
FS/UI/agent.pm
FS/UID.pm
FS/Msgcat.pm
+FS/acct_snarf.pm
FS/agent.pm
FS/agent_type.pm
FS/cust_bill.pm
@@ -71,6 +71,8 @@ FS/part_export/apache.pm
FS/part_export/bind.pm
FS/part_export/bind_slave.pm
FS/part_export/bsdshell.pm
+FS/part_export/communigate_pro.pm
+FS/part_export/communigate_pro_singledomain.pm
FS/part_export/cp.pm
FS/part_export/cyrus.pm
FS/part_export/domain_shellcommands.pm
@@ -100,6 +102,7 @@ FS/svc_acct.pm
FS/svc_acct_pop.pm
FS/svc_broadband.pm
FS/svc_domain.pm
+FS/svc_external.pm
FS/router.pm
FS/type_pkgs.pm
FS/nas.pm
@@ -182,8 +185,10 @@ t/radius_usergroup.t
t/session.t
t/svc_acct.t
t/svc_acct_pop.t
+t/svc_broadband.t
t/svc_Common.t
t/svc_domain.t
+t/svc_external.t
t/svc_forward.t
t/svc_www.t
t/type_pkgs.t
diff --git a/FS/bin/freeside-addoutsourceuser b/FS/bin/freeside-addoutsourceuser
index 180cd9399..abb515b6f 100644
--- a/FS/bin/freeside-addoutsourceuser
+++ b/FS/bin/freeside-addoutsourceuser
@@ -10,6 +10,6 @@ freeside-adduser -h /usr/local/etc/freeside/htpasswd \
$username $password 2>/dev/null
[ -e /usr/local/etc/freeside/dbdef.DBI:Pg:host=localhost\;dbname=$domain ] \
- || ( freeside-setup $username 2>/dev/null; \
- /home/ivan/freeside/bin/populate-msgcat $username )
+ || ( freeside-setup -s $username 2>/dev/null; \
+ /home/ivan/freeside/bin/populate-msgcat $username 2>/dev/null )
diff --git a/FS/bin/freeside-daily b/FS/bin/freeside-daily
index 63e621b57..5fb966665 100755
--- a/FS/bin/freeside-daily
+++ b/FS/bin/freeside-daily
@@ -10,8 +10,8 @@ use FS::Conf;
use FS::cust_main;
&untaint_argv; #what it sounds like (eww)
-use vars qw($opt_d $opt_v $opt_p);
-getopts("p:d:v");
+use vars qw($opt_d $opt_v $opt_p $opt_s $opt_y);
+getopts("p:d:vsy:");
my $user = shift or die &usage;
adminsuidsetup $user;
@@ -28,6 +28,7 @@ my @cust_main = @ARGV
#we're at now now (and later).
my($time)= $opt_d ? str2time($opt_d) : $^T;
+$time += $opt_y * 86400 if $opt_y;
my($cust_main,%saw);
foreach $cust_main ( @cust_main ) {
@@ -42,7 +43,8 @@ foreach $cust_main ( @cust_main ) {
if $error;
}
- my $error = $cust_main->bill( 'time' => $time );
+ my $error = $cust_main->bill( 'time' => $time,
+ 'resetup' => $opt_s, );
warn "Error billing, custnum ". $cust_main->custnum. ": $error" if $error;
$cust_main->apply_payments;
@@ -98,7 +100,7 @@ freeside-daily - Run daily billing and invoice collection events.
=head1 SYNOPSIS
- freeside-daily [ -d 'date' ] [ -p 'payby' ] [ -v ] user [ custnum custnum ... ]
+ freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -s ] [ -v ] user [ custnum custnum ... ]
=head1 DESCRIPTION
@@ -113,8 +115,15 @@ the bill and collect methods of a cust_main object. See L<FS::cust_main>.
-d: Pretend it's 'date'. Date is in any format Date::Parse is happy with,
but be careful.
+ -y: In addition to -d, which specifies an absolute date, the -y switch
+ specifies an offset, in days. For example, "-y 15" would increment the
+ "pretend date" 15 days from whatever was specified by the -d switch
+ (or now, if no -d switch was given).
+
-p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
+ -s: re-charge setup fees
+
-v: enable debugging
user: From the mapsecrets file - see config.html from the base documentation
diff --git a/FS/bin/freeside-receivables-report b/FS/bin/freeside-receivables-report
deleted file mode 100755
index f3ad2a1a6..000000000
--- a/FS/bin/freeside-receivables-report
+++ /dev/null
@@ -1,217 +0,0 @@
-#!/usr/bin/perl -Tw
-
-use strict;
-use Date::Parse;
-use Time::Local;
-use Getopt::Std;
-use Text::Template;
-use Net::SMTP;
-use Mail::Header;
-use Mail::Internet;
-use FS::Conf;
-use FS::UID qw(adminsuidsetup);
-use FS::Record qw(qsearch);
-use FS::cust_main;
-
-
-&untaint_argv; #what it sounds like (eww)
-use vars qw($opt_v $opt_p $opt_m $opt_e $opt_t $report_lines $report_template @buf $header);
-getopts("vpmet:"); #switches
-
-#we're at now now (and later).
-my($_date)= $^T;
-
-# Get the current month
-my ($sec,$min,$hour,$mday,$mon,$year) =
- (localtime($_date) )[0,1,2,3,4,5];
-$mon++;
-$year += 1900;
-
-# Login to the database
-my $user = shift or die &usage;
-adminsuidsetup $user;
-
-# Get the needed configuration files
-my $conf = new FS::Conf;
-my $lpr = $conf->config('lpr');
-my $email = $conf->config('email');
-my $smtpmachine = $conf->config('smtpmachine');
-my $mail_sender = $conf->exists('invoice_from') ? $conf->config('invoice_from') :
- 'postmaster';
-my @report_template = $conf->config('report_template')
- or die "cannot load config file report_template";
-$report_lines = 0;
- foreach ( grep /report_lines\(\d+\)/, @report_template ) { #kludgy :/
- /report_lines\((\d+)\)/;
- $report_lines += $1;
-}
-die "no report_lines() functions in template?" unless $report_lines;
-$report_template = new Text::Template (
- TYPE => 'ARRAY',
- SOURCE => [ map "$_\n", @report_template ],
-) or die "can't create new Text::Template object: $Text::Template::ERROR";
-
-
-my(@customers)=qsearch('cust_main',{});
-if (scalar(@customers) == 0)
-{
- exit 1;
-}
-
-# Open print and email pipes
-# $lpr and opt_p for printing
-# $email and opt_m for email
-
-if ($lpr && $opt_p)
-{
- open(LPR, "|$lpr");
-}
-
-if ($email && $opt_m)
-{
- $ENV{MAILADDRESS} = $mail_sender;
- $header = new Mail::Header ( [
- "From: Account Processor",
- "To: $email",
- "Sender: $mail_sender",
- "Reply-To: $mail_sender",
- "Subject: Receivables",
- ] );
-}
-
-my $total = 0;
-
-
-# Now I can start looping
-foreach my $customer (@customers)
-{
- my $custnum = $customer->getfield('custnum');
- my $first = $customer->getfield('first');
- my $last = $customer->getfield('last');
- my $company = $customer->getfield('company');
- my $daytime = $customer->getfield('daytime');
- my $balance = $customer->balance;
-
-
- if ($balance != 0) {
- $total += $balance;
- push @buf, sprintf(qq{%8d %-32.32s %12s %9.2f},
- $custnum,
- $first . " " . $last . " " . $company,
- $daytime,
- $balance);
-
- }
-
-}
-
-push @buf, ('', sprintf(qq{%61s}, "========="), sprintf(qq{%61.2f}, $total));
-
-sub FS::receivables_report::_template::report_lines {
- my $lines = shift;
- map {
- scalar(@buf) ? shift @buf : '' ;
- }
- ( 1 .. $lines );
-}
-
-$FS::receivables_report::_template::title = " R E C E I V A B L E S ";
-$FS::receivables_report::_template::title = $opt_t if $opt_t;
-$FS::receivables_report::_template::page = 1;
-$FS::receivables_report::_template::date = $_date;
-$FS::receivables_report::_template::date = $_date;
-$FS::receivables_report::_template::total_pages =
- int( scalar(@buf) / $report_lines);
-$FS::receivables_report::_template::total_pages++ if scalar(@buf) % $report_lines;
-
-my @report;
-while (@buf) {
- push @report, split("\n",
- $report_template->fill_in( PACKAGE => 'FS::receivables_report::_template' )
- );
- $FS::receivables_report::_template::page++;
-}
-
-if ($opt_v) {
- print map "$_\n", @report;
-}
-if($lpr && $opt_p)
-{
- print LPR map "$_\n", @report;
- print LPR "\f" if $opt_e;
- close LPR || die "Could not close printer: $lpr\n";
-}
-if($email && $opt_m)
-{
- my $message = new Mail::Internet (
- 'Header' => $header,
- 'Body' => [ (@report) ],
- );
- $!=0;
- $message->smtpsend( Host => "$smtpmachine" )
- or die "can't send report to $email via $smtpmachine: $!";
-}
-
-
-# subroutines
-
-sub untaint_argv {
- foreach $_ ( $[ .. $#ARGV ) { #untaint @ARGV
- $ARGV[$_] =~ /^([\w\-\/ \.]*)$/ || die "Illegal argument \"$ARGV[$_]\"";
- $ARGV[$_]=$1;
- }
-}
-
-sub usage {
- die "Usage:\n\n freeside-receivables-report [-v] [-p] [-e] user\n";
-}
-
-=head1 NAME
-
-freeside-receivables-report - Prints or emails outstanding receivables.
-
-=head1 SYNOPSIS
-
- freeside-receivables-report [-v] [-p] [-m] [-e] [-t "title"] user
-
-=head1 DESCRIPTION
-
-Prints or emails outstanding receivables
-
-B<-v>: Verbose - Prints records to STDOUT.
-
-B<-p>: Print to printer lpr as found in the conf directory.
-
-B<-m>: Mail output to user found in the Conf email file.
-
-B<-e>: Print a final form feed to the printer.
-
-B<-t>: supply a title for the top of each page.
-
-user: From the mapsecrets file - see config.html from the base documentation
-
-=head1 VERSION
-
-$Id: freeside-receivables-report,v 1.6 2002-09-09 22:57:34 ivan Exp $
-
-=head1 BUGS
-
-Yes..... Use at your own risk. No guarantees or warrantees of any
-kind apply to this program. Parts of this program are hacked from
-other GNU licensed software created mainly by Ivan Kohler.
-
-This is released under the GNU Public License. See www.gnu.org
-for more information regarding this license.
-
-=head1 SEE ALSO
-
-L<FS::cust_main>, config.html from the base documentation
-
-=head1 AUTHOR
-
-Jeff Finucane <jeff@cmh.net>
-
-based on print-batch by Joel Griffiths <griff@aver-computer.com>
-
-=cut
-
diff --git a/FS/bin/freeside-selfservice-server b/FS/bin/freeside-selfservice-server
index 264cbc56d..371a646b4 100644
--- a/FS/bin/freeside-selfservice-server
+++ b/FS/bin/freeside-selfservice-server
@@ -9,6 +9,7 @@
use strict;
use vars qw( $Debug %kids $kids $max_kids $shutdown $log_file $ssh_pid );
+use subs qw( lock_write unlock_write );
use Fcntl qw(:flock);
use POSIX qw(:sys_wait_h setsid);
use IO::Handle;
@@ -32,18 +33,18 @@ $kids = 0;
my $user = shift or die &usage;
my $machine = shift or die &usage;
-my $pid_file = "/var/run/freeside-selfservice-server.$user.pid";
-#my $pid_file = "/var/run/freeside-selfservice-server.$user.pid"; $FS::UID::datasrc not posible, but should include machine name at least, hmm
+my $tag = scalar(@ARGV) ? shift : '';
+
+# $FS::UID::datasrc not posible
+my $pid_file = "/var/run/freeside-selfservice-server.$user.$machine.pid";
+
+my $lock_file = "/usr/local/etc/freeside/selfservice.$machine.writelock";
+open(LOCKFILE,">$lock_file") or die "can't open $lock_file: $!";
&init($user);
my $conf = new FS::Conf;
-if ($conf->exists('selfservice_server-quiet')) {
- $FS::cust_bill::quiet = 1;
- $FS::cust_pkg::quiet = 1;
-}
-
my $clientd = "/usr/local/sbin/freeside-selfservice-clientd"; #better name?
my $warnkids=0;
@@ -51,7 +52,7 @@ while (1) {
my($writer,$reader,$error) = (new IO::Handle, new IO::Handle, new IO::Handle);
warn "connecting to $machine\n" if $Debug;
- $ssh_pid = sshopen2($machine,$reader,$writer,$clientd);
+ $ssh_pid = sshopen2($machine,$reader,$writer,$clientd,$tag);
# nstore_fd(\*writer, {'hi'=>'there'});
@@ -74,7 +75,18 @@ while (1) {
warn "receiving packet from client\n" if $Debug;
- my $packet = fd_retrieve($reader);
+ my $packet = eval { fd_retrieve($reader); };
+ if ( $@ ) {
+ warn "Storable error receiving packet from client".
+ " (assuming lost connection): $@\n"
+ if $Debug;
+ if ( $ssh_pid ) {
+ warn "sending TERM signal to ssh process $ssh_pid\n" if $Debug;
+ kill 'TERM', $ssh_pid;
+ $ssh_pid = 0;
+ }
+ last;
+ }
warn "packet received\n".
join('', map { " $_=>$packet->{$_}\n" } keys %$packet )
if $Debug > 1;
@@ -109,10 +121,10 @@ while (1) {
$rv->{_token} = $packet->{_token}; #identifier
warn "sending response\n" if $Debug;
- flock($writer, LOCK_EX) or die "FATAL: can't lock write stream: $!";
+ lock_write;
nstore_fd($rv, $writer) or die "FATAL: can't send response: $!";
$writer->flush or die "FATAL: can't flush: $!";
- flock($writer, LOCK_UN) or die "WARNING: can't release write lock: $!";
+ unlock_write;
warn "child exiting\n" if $Debug;
exit; #end-of-kid
@@ -120,6 +132,9 @@ while (1) {
}
+ warn "connection lost, reconnecting\n" if $Debug;
+ sleep 3;
+
}
###
@@ -229,7 +244,23 @@ sub _do_logmsg {
close $log;
}
+sub lock_write {
+ #broken on freebsd?
+ #flock($writer, LOCK_EX) or die "FATAL: can't lock write stream: $!";
+
+ flock(LOCKFILE, LOCK_EX) or die "FATAL: can't lock $lock_file: $!";
+
+}
+
+sub unlock_write {
+ #broken on freebsd?
+ #flock($writer, LOCK_UN) or die "WARNING: can't release write lock: $!";
+
+ flock(LOCKFILE, LOCK_UN) or die "FATAL: can't unlock $lock_file: $!";
+
+}
+
sub usage {
- die "Usage:\n\n fs_signup_server user machine\n";
+ die "Usage:\n\n freeside-selfservice-server user machine\n";
}
diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup
index 2cb555e18..7512cc18c 100755
--- a/FS/bin/freeside-setup
+++ b/FS/bin/freeside-setup
@@ -336,10 +336,13 @@ sub tables_hash_hack {
'typenum', 'int', '', '',
'freq', 'int', 'NULL', '',
'prog', @perl_type,
+ 'disabled', 'char', 'NULL', 1,
+ 'username', 'varchar', 'NULL', $char_d,
+ '_password','varchar', 'NULL', $char_d,
],
'primary_key' => 'agentnum',
'unique' => [],
- 'index' => [ ['typenum'] ],
+ 'index' => [ ['typenum'], ['disabled'] ],
},
'agent_type' => {
@@ -405,7 +408,7 @@ sub tables_hash_hack {
],
'primary_key' => 'eventpart',
'unique' => [],
- 'index' => [ ['payby'] ],
+ 'index' => [ ['payby'], ['disabled'], ],
},
'cust_bill_pkg' => {
@@ -499,6 +502,7 @@ sub tables_hash_hack {
'ship_fax', 'varchar', 'NULL', 12,
'payby', 'char', '', 4,
'payinfo', 'varchar', 'NULL', $char_d,
+ 'paycvv', 'varchar', 'NULL', 4,
#'paydate', @date_type,
'paydate', 'varchar', 'NULL', 10,
'payname', 'varchar', 'NULL', $char_d,
@@ -539,6 +543,8 @@ sub tables_hash_hack {
'exempt_amount', @money_type,
'tax', 'real', '', '', #tax %
'taxname', 'varchar', 'NULL', $char_d,
+ 'setuptax', 'char', 'NULL', 1, # Y = setup tax exempt
+ 'recurtax', 'char', 'NULL', 1, # Y = recur tax exempt
],
'primary_key' => 'taxnum',
'unique' => [],
@@ -561,7 +567,7 @@ sub tables_hash_hack {
],
'primary_key' => 'paynum',
'unique' => [],
- 'index' => [ [ 'custnum' ], [ 'paybatch' ] ],
+ 'index' => [ [ 'custnum' ], [ 'paybatch' ], [ 'payby' ], [ '_date' ] ],
},
'cust_bill_pay' => {
@@ -673,7 +679,7 @@ sub tables_hash_hack {
'pkg', 'varchar', '', $char_d,
'comment', 'varchar', '', $char_d,
'setup', @perl_type,
- 'freq', 'int', '', '', #billing frequency (months)
+ 'freq', 'varchar', '', $char_d, #billing frequency
'recur', @perl_type,
'setuptax', 'char', 'NULL', 1,
'recurtax', 'char', 'NULL', 1,
@@ -702,6 +708,7 @@ sub tables_hash_hack {
'pkgpart', 'int', '', '',
'svcpart', 'int', '', '',
'quantity', 'int', '', '',
+ 'primary_svc','char', 'NULL', 1,
],
'primary_key' => '',
'unique' => [ ['pkgpart', 'svcpart'] ],
@@ -712,10 +719,11 @@ sub tables_hash_hack {
'columns' => [
'refnum', 'serial', '', '',
'referral', 'varchar', '', $char_d,
+ 'disabled', 'char', 'NULL', 1,
],
'primary_key' => 'refnum',
'unique' => [],
- 'index' => [],
+ 'index' => [ ['disabled'] ],
},
'part_svc' => {
@@ -776,7 +784,7 @@ sub tables_hash_hack {
'columns' => [
'svcnum', 'int', '', '',
'username', 'varchar', '', $username_len, #unique (& remove dup code)
- '_password', 'varchar', '', 50, #13 for encryped pw's plus ' *SUSPENDED* (mp5 passwords can be 34)
+ '_password', 'varchar', '', 72, #13 for encryped pw's plus ' *SUSPENDED* (md5 passwords can be 34, blowfish 60)
'sec_phrase', 'varchar', 'NULL', $char_d,
'popnum', 'int', 'NULL', '',
'uid', 'int', 'NULL', '',
@@ -834,10 +842,11 @@ sub tables_hash_hack {
'svc_forward' => {
'columns' => [
- 'svcnum', 'int', '', '',
- 'srcsvc', 'int', '', '',
- 'dstsvc', 'int', '', '',
- 'dst', 'varchar', 'NULL', $char_d,
+ 'svcnum', 'int', '', '',
+ 'srcsvc', 'int', 'NULL', '',
+ 'src', 'varchar', 'NULL', 255,
+ 'dstsvc', 'int', 'NULL', '',
+ 'dst', 'varchar', 'NULL', 255,
],
'primary_key' => 'svcnum',
'unique' => [],
@@ -1099,6 +1108,31 @@ sub tables_hash_hack {
'index' => [],
},
+ 'acct_snarf' => {
+ 'columns' => [
+ 'snarfnum', 'int', '', '',
+ 'svcnum', 'int', '', '',
+ 'machine', 'varchar', '', 255,
+ 'protocol', 'varchar', '', $char_d,
+ 'username', 'varchar', '', $char_d,
+ '_password', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'snarfnum',
+ 'unique' => [],
+ 'index' => [ [ 'svcnum' ] ],
+ },
+
+ 'svc_external' => {
+ 'columns' => [
+ 'svcnum', 'int', '', '',
+ 'id', 'int', '', '',
+ 'title', 'varchar', 'NULL', $char_d,
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
);
%tables;
diff --git a/FS/t/acct_snarf.t b/FS/t/acct_snarf.t
new file mode 100644
index 000000000..642760f20
--- /dev/null
+++ b/FS/t/acct_snarf.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::acct_snarf;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/svc_broadband.t b/FS/t/svc_broadband.t
new file mode 100644
index 000000000..02dc1124a
--- /dev/null
+++ b/FS/t/svc_broadband.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::svc_broadband;
+$loaded=1;
+print "ok 1\n";
diff --git a/FS/t/svc_external.t b/FS/t/svc_external.t
new file mode 100644
index 000000000..20a676784
--- /dev/null
+++ b/FS/t/svc_external.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::svc_external;
+$loaded=1;
+print "ok 1\n";