summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
Diffstat (limited to 'FS')
-rw-r--r--FS/FS.pm36
-rw-r--r--FS/FS/ClientAPI.pm27
-rw-r--r--FS/FS/ClientAPI/Agent.pm31
-rw-r--r--FS/FS/ClientAPI/MyAccount.pm123
-rw-r--r--FS/FS/ClientAPI/Signup.pm49
-rw-r--r--FS/FS/ClientAPI/passwd.pm7
-rw-r--r--FS/FS/ClientAPI_SessionCache.pm78
-rw-r--r--FS/FS/Conf.pm306
-rw-r--r--FS/FS/ConfItem.pm2
-rw-r--r--FS/FS/Daemon.pm91
-rw-r--r--FS/FS/Misc.pm227
-rw-r--r--FS/FS/Record.pm381
-rw-r--r--FS/FS/Report/Table/Monthly.pm38
-rw-r--r--FS/FS/Schema.pm1277
-rw-r--r--FS/FS/TicketSystem.pm4
-rw-r--r--FS/FS/TicketSystem/RT_External.pm158
-rw-r--r--FS/FS/TicketSystem/RT_Internal.pm33
-rw-r--r--FS/FS/UI/Base.pm194
-rw-r--r--FS/FS/UI/CGI.pm239
-rw-r--r--FS/FS/UI/Gtk.pm224
-rw-r--r--FS/FS/UI/Web.pm267
-rw-r--r--FS/FS/UI/agent.pm62
-rw-r--r--FS/FS/UID.pm2
-rw-r--r--FS/FS/XMLRPC.pm165
-rw-r--r--FS/FS/agent.pm139
-rw-r--r--FS/FS/agent_payment_gateway.pm139
-rw-r--r--FS/FS/banned_pay.pm136
-rw-r--r--FS/FS/cancel_reason.pm123
-rw-r--r--FS/FS/clientapi_session.pm121
-rw-r--r--FS/FS/clientapi_session_field.pm126
-rw-r--r--FS/FS/cust_bill.pm1566
-rw-r--r--FS/FS/cust_bill_event.pm106
-rw-r--r--FS/FS/cust_bill_pkg.pm42
-rw-r--r--FS/FS/cust_bill_pkg_detail.pm2
-rw-r--r--FS/FS/cust_credit.pm11
-rw-r--r--FS/FS/cust_main.pm1010
-rw-r--r--FS/FS/cust_main_Mixin.pm103
-rw-r--r--FS/FS/cust_main_county.pm9
-rw-r--r--FS/FS/cust_main_invoice.pm8
-rw-r--r--FS/FS/cust_pay.pm110
-rw-r--r--FS/FS/cust_pay_refund.pm16
-rw-r--r--FS/FS/cust_pay_void.pm54
-rw-r--r--FS/FS/cust_pkg.pm320
-rw-r--r--FS/FS/cust_refund.pm6
-rw-r--r--FS/FS/cust_svc.pm70
-rw-r--r--FS/FS/domain_record.pm39
-rw-r--r--FS/FS/export_svc.pm125
-rw-r--r--FS/FS/h_Common.pm26
-rw-r--r--FS/FS/h_cust_svc.pm49
-rw-r--r--FS/FS/h_domain_record.pm33
-rw-r--r--FS/FS/h_svc_acct.pm29
-rw-r--r--FS/FS/h_svc_forward.pm40
-rw-r--r--FS/FS/h_svc_www.pm26
-rw-r--r--FS/FS/option_Common.pm295
-rw-r--r--FS/FS/part_bill_event.pm34
-rw-r--r--FS/FS/part_export.pm140
-rw-r--r--FS/FS/part_export/acct_sql.pm105
-rw-r--r--FS/FS/part_export/artera_turbo.pm54
-rw-r--r--FS/FS/part_export/cp.pm5
-rw-r--r--FS/FS/part_export/cpanel.pm192
-rw-r--r--FS/FS/part_export/domain_shellcommands.pm1
-rw-r--r--FS/FS/part_export/everyone_net.pm132
-rw-r--r--FS/FS/part_export/forward_shellcommands.pm51
-rw-r--r--FS/FS/part_export/http.pm2
-rw-r--r--FS/FS/part_export/infostreet.pm2
-rw-r--r--FS/FS/part_export/radiator.pm167
-rw-r--r--FS/FS/part_export/shellcommands.pm76
-rw-r--r--FS/FS/part_export/shellcommands_withdomain.pm13
-rw-r--r--FS/FS/part_export/sqlradius.pm95
-rw-r--r--FS/FS/part_export/sqlradius_withdomain.pm2
-rw-r--r--FS/FS/part_export/www_shellcommands.pm1
-rw-r--r--FS/FS/part_export_option.pm2
-rw-r--r--FS/FS/part_pkg.pm80
-rw-r--r--FS/FS/part_pkg/flat.pm56
-rw-r--r--FS/FS/part_pkg/flat_comission.pm44
-rw-r--r--FS/FS/part_pkg/flat_comission_cust.pm53
-rw-r--r--FS/FS/part_pkg/flat_comission_pkg.pm60
-rw-r--r--FS/FS/part_pkg/flat_delayed.pm40
-rw-r--r--FS/FS/part_pkg/prepaid.pm28
-rw-r--r--FS/FS/part_pkg/prorate.pm34
-rw-r--r--FS/FS/part_pkg/sesmon_hour.pm49
-rw-r--r--FS/FS/part_pkg/sesmon_minute.pm49
-rw-r--r--FS/FS/part_pkg/sql_external.pm53
-rw-r--r--FS/FS/part_pkg/sql_generic.pm69
-rw-r--r--FS/FS/part_pkg/sqlradacct_hour.pm131
-rw-r--r--FS/FS/part_pkg/subscription.pm30
-rw-r--r--FS/FS/part_pkg/voip_sqlradacct.pm118
-rw-r--r--FS/FS/part_svc.pm269
-rwxr-xr-xFS/FS/part_svc_router.pm3
-rwxr-xr-xFS/FS/part_virtual_field.pm5
-rw-r--r--FS/FS/payment_gateway.pm147
-rw-r--r--FS/FS/payment_gateway_option.pm126
-rw-r--r--FS/FS/pkg_svc.pm5
-rw-r--r--FS/FS/prepay_credit.pm74
-rw-r--r--FS/FS/queue.pm35
-rw-r--r--FS/FS/raddb.pm3417
-rw-r--r--FS/FS/rate.pm169
-rw-r--r--FS/FS/rate_detail.pm5
-rw-r--r--FS/FS/rate_prefix.pm2
-rw-r--r--FS/FS/reg_code.pm223
-rw-r--r--FS/FS/reg_code_pkg.pm138
-rw-r--r--FS/FS/svc_Common.pm56
-rw-r--r--FS/FS/svc_acct.pm362
-rw-r--r--FS/FS/svc_domain.pm1
-rw-r--r--FS/FS/svc_forward.pm6
-rw-r--r--FS/FS/svc_www.pm8
-rw-r--r--FS/FS/type_pkgs.pm5
-rw-r--r--FS/MANIFEST37
-rw-r--r--FS/bin/freeside-addoutsource20
-rw-r--r--FS/bin/freeside-addoutsourceuser4
-rwxr-xr-xFS/bin/freeside-daily90
-rw-r--r--FS/bin/freeside-prepaidd75
-rw-r--r--FS/bin/freeside-queued109
-rw-r--r--FS/bin/freeside-selfservice-server131
-rwxr-xr-xFS/bin/freeside-setup1086
-rw-r--r--FS/bin/freeside-sqlradius-radacctd212
-rwxr-xr-xFS/bin/freeside-sqlradius-reset3
-rwxr-xr-xFS/bin/freeside-upgrade131
-rw-r--r--FS/t/ClientAPI_SessionCache.t5
-rw-r--r--FS/t/Daemon.t5
-rw-r--r--FS/t/agent_payment_gateway.t5
-rw-r--r--FS/t/banned_pay.t5
-rw-r--r--FS/t/cancel_reason.t5
-rw-r--r--FS/t/clientapi_session.t5
-rw-r--r--FS/t/clientapi_session_field.t5
-rw-r--r--FS/t/cust_main_Mixin.t5
-rw-r--r--FS/t/h_domain_record.t5
-rw-r--r--FS/t/option_Common.t5
-rw-r--r--FS/t/part_export-radiator.t5
-rw-r--r--FS/t/payment_gateway.t5
-rw-r--r--FS/t/payment_gateway_option.t5
-rw-r--r--FS/t/reg_code.t5
-rw-r--r--FS/t/reg_code_pkg.t5
133 files changed, 5283 insertions, 12614 deletions
diff --git a/FS/FS.pm b/FS/FS.pm
index f41245e22..3bbd66fb6 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -88,10 +88,6 @@ L<FS::part_pkg_option> - Package definition option class
L<FS::pkg_svc> - Class linking package definitions (see L<FS::part_pkg>) with
service definitions (see L<FS::part_svc>)
-L<FS::reg_code> - One-time registration codes
-
-L<FS::reg_code_pkg> - Class linking registration codes (see L<FS::reg_code>) with package definitions (see L<FS::part_pkg>)
-
L<FS::rate> - Rate plans for call billing
L<FS::rate_region> - Rate regions for call billing
@@ -160,24 +156,6 @@ L<FS::queue_depend> - Job dependencies
L<FS::msgcat> - Message catalogs
-L<FS::clientapi_session>
-
-L<FS::clientapi_session_field>
-
-=head1 Client API
-
-L<FS::ClientAPI>
-
-L<FS::ClientAPI_SessionCache>
-
-L<FS::ClientAPI::Signup>
-
-L<FS::ClientAPI::passwd>
-
-L<FS::ClientAPI::MyAccount>
-
-L<FS::ClientAPI::Agent>
-
=head1 Remote API modules
L<FS::SelfService>
@@ -212,9 +190,15 @@ L<freeside-bill>
L<freeside-overdue>
-=head2 User Interface classes
+=head2 User Interface classes (under (stalled) development; not yet usable)
+
+L<FS::UI::Base> - User-interface base class
+
+L<FS::UI::Gtk> - Gtk user-interface class
+
+L<FS::UI::CGI> - CGI (HTML) user-interface class
-L<FS::UI::Web> - Web user-interface class
+L<FS::UI::agent> - agent table user-interface class
=head2 Notes
@@ -237,11 +221,11 @@ The main documentation is in httemplate/docs.
=head1 SUPPORT
A mailing list for users is available. Send a blank message to
-<freeside-users-subscribe@sisd.com> to subscribe.
+<ivan-freeside-subscribe@sisd.com> to subscribe.
A mailing list for developers is available. It is intended to be lower volume
and higher SNR than the users list. Send a blank message to
-<freeside-devel-subscribe@sisd.com> to subscribe.
+<ivan-freeside-devel-subscribe@sisd.com> to subscribe.
Commercial support is available; see
<http://www.sisd.com/freeside/commercial.html>.
diff --git a/FS/FS/ClientAPI.pm b/FS/FS/ClientAPI.pm
index 902f58b31..7cbbdbf67 100644
--- a/FS/FS/ClientAPI.pm
+++ b/FS/FS/ClientAPI.pm
@@ -1,35 +1,42 @@
package FS::ClientAPI;
use strict;
-use vars qw(%handler $domain $DEBUG);
-
-$DEBUG = 0;
+use vars qw(%handler $domain);
%handler = ();
#find modules
foreach my $INC ( @INC ) {
- my $glob = "$INC/FS/ClientAPI/*.pm";
- warn "FS::ClientAPI: searching $glob" if $DEBUG;
- foreach my $file ( glob($glob) ) {
+ foreach my $file ( glob("$INC/FS/ClientAPI/*.pm") ) {
$file =~ /\/(\w+)\.pm$/ or do {
warn "unrecognized ClientAPI file: $file";
next
};
my $mod = $1;
- warn "using FS::ClientAPI::$mod" if $DEBUG;
+ #warn "using FS::ClientAPI::$mod";
eval "use FS::ClientAPI::$mod;";
die "error using FS::ClientAPI::$mod: $@" if $@;
}
}
+#(sub for modules)
+sub register_handlers {
+ my $self = shift;
+ my %new_handlers = @_;
+ foreach my $key ( keys %new_handlers ) {
+ warn "WARNING: redefining sub $key" if exists $handler{$key};
+ #warn "registering $key";
+ $handler{$key} = $new_handlers{$key};
+ }
+}
+
#---
sub dispatch {
my ( $self, $name ) = ( shift, shift );
- $name =~ s(/)(::)g;
- my $sub = "FS::ClientAPI::$name";
- no strict 'refs';
+ my $sub = $handler{$name}
+ or die "unknown FS::ClientAPI sub $name (known: ". join(" ", keys %handler );
+ #or die "unknown FS::ClientAPI sub $name";
&{$sub}(@_);
}
diff --git a/FS/FS/ClientAPI/Agent.pm b/FS/FS/ClientAPI/Agent.pm
index daede59a8..f534a8685 100644
--- a/FS/FS/ClientAPI/Agent.pm
+++ b/FS/FS/ClientAPI/Agent.pm
@@ -4,18 +4,24 @@ package FS::ClientAPI::Agent;
use strict;
use vars qw($cache);
-use subs qw(_cache);
use Digest::MD5 qw(md5_hex);
+use Cache::SharedMemoryCache; #store in db?
use FS::Record qw(qsearchs); # qsearch dbdef dbh);
-use FS::ClientAPI_SessionCache;
use FS::agent;
use FS::cust_main qw(smart_search);
-sub _cache {
- $cache ||= new FS::ClientAPI_SessionCache( {
- 'namespace' => 'FS::ClientAPI::Agent',
- } );
-}
+use FS::ClientAPI;
+FS::ClientAPI->register_handlers(
+ 'Agent/agent_login' => \&agent_login,
+ 'Agent/agent_logout' => \&agent_logout,
+ 'Agent/agent_info' => \&agent_info,
+ 'Agent/agent_list_customers' => \&agent_list_customers,
+);
+
+#store in db?
+my $cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::Agent',
+} );
sub agent_login {
my $p = shift;
@@ -39,9 +45,9 @@ sub agent_login {
my $session_id;
do {
$session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
- } until ( ! defined _cache->get($session_id) ); #just in case
+ } until ( ! defined $cache->get($session_id) ); #just in case
- _cache->set( $session_id, $session, '1 hour' );
+ $cache->set( $session_id, $session, '1 hour' );
{ 'error' => '',
'session_id' => $session_id,
@@ -51,7 +57,7 @@ sub agent_login {
sub agent_logout {
my $p = shift;
if ( $p->{'session_id'} ) {
- _cache->remove($p->{'session_id'});
+ $cache->remove($p->{'session_id'});
return { 'error' => '' };
} else {
return { 'error' => "Can't resume session" }; #better error message
@@ -61,7 +67,7 @@ sub agent_logout {
sub agent_info {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
#my %return;
@@ -86,7 +92,7 @@ sub agent_info {
sub agent_list_customers {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
#my %return;
@@ -122,4 +128,3 @@ sub agent_list_customers {
}
-1;
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index 4b67f53af..fe2e1c228 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -2,16 +2,14 @@ package FS::ClientAPI::MyAccount;
use strict;
use vars qw($cache);
-use subs qw(_cache);
use Digest::MD5 qw(md5_hex);
use Date::Format;
use Business::CreditCard;
-use Time::Duration;
+use Cache::SharedMemoryCache; #store in db?
use FS::CGI qw(small_custview); #doh
use FS::Conf;
use FS::Record qw(qsearch qsearchs);
use FS::Msgcat qw(gettext);
-use FS::ClientAPI_SessionCache;
use FS::svc_acct;
use FS::svc_domain;
use FS::svc_external;
@@ -21,22 +19,42 @@ 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/logout' => \&logout,
+ 'MyAccount/customer_info' => \&customer_info,
+ 'MyAccount/edit_info' => \&edit_info,
+ 'MyAccount/invoice' => \&invoice,
+ 'MyAccount/list_invoices' => \&list_invoices,
+ '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,
+ 'MyAccount/part_svc_info' => \&part_svc_info,
+ 'MyAccount/provision_acct' => \&provision_acct,
+ 'MyAccount/provision_external' => \&provision_external,
+ 'MyAccount/unprovision_svc' => \&unprovision_svc,
+);
+
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
- payby payinfo payname paystart_month paystart_year payissue payip
+ payby payinfo payname
);
use subs qw(_provision);
-sub _cache {
- $cache ||= new FS::ClientAPI_SessionCache( {
- 'namespace' => 'FS::ClientAPI::MyAccount',
- } );
-}
+#store in db?
+my $cache = new Cache::SharedMemoryCache( {
+ 'namespace' => 'FS::ClientAPI::MyAccount',
+} );
#false laziness w/FS::ClientAPI::passwd::passwd
sub login {
@@ -72,9 +90,9 @@ sub login {
my $session_id;
do {
$session_id = md5_hex(md5_hex(time(). {}. rand(). $$))
- } until ( ! defined _cache->get($session_id) ); #just in case
+ } until ( ! defined $cache->get($session_id) ); #just in case
- _cache->set( $session_id, $session, '1 hour' );
+ $cache->set( $session_id, $session, '1 hour' );
return { 'error' => '',
'session_id' => $session_id,
@@ -84,7 +102,7 @@ sub login {
sub logout {
my $p = shift;
if ( $p->{'session_id'} ) {
- _cache->remove($p->{'session_id'});
+ $cache->remove($p->{'session_id'});
return { 'error' => '' };
} else {
return { 'error' => "Can't resume session" }; #better error message
@@ -118,7 +136,7 @@ sub customer_info {
my $conf = new FS::Conf;
$return{small_custview} =
- small_custview( $cust_main, $conf->config('countrydefault') );
+ small_custview( $cust_main, $conf->config('defaultcountry') );
$return{name} = $cust_main->first. ' '. $cust_main->get('last');
@@ -132,20 +150,16 @@ sub customer_info {
}
$return{'invoicing_list'} =
- join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list );
+ join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list );
$return{'postal_invoicing'} =
0 < ( grep { $_ eq 'POST' } $cust_main->invoicing_list );
- } elsif ( $session->{'svcnum'} ) { #no customer record
+ } else { #no customer record
my $svc_acct = qsearchs('svc_acct', { 'svcnum' => $session->{'svcnum'} } )
or die "unknown svcnum";
$return{name} = $svc_acct->email;
- } else {
-
- return { 'error' => 'Expired session' }; #XXX redirect to login w/this err!
-
}
return { 'error' => '',
@@ -157,7 +171,7 @@ sub customer_info {
sub edit_info {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
my $custnum = $session->{'custnum'}
@@ -197,7 +211,7 @@ sub edit_info {
sub payment_info {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
##
@@ -207,7 +221,7 @@ sub payment_info {
my $conf = new FS::Conf;
my %states = map { $_->state => 1 }
qsearch('cust_main_county', {
- 'country' => $conf->config('countrydefault') || 'US'
+ 'country' => $conf->config('defaultcountry') || 'US'
} );
use vars qw($payment_info); #cache for performance
@@ -226,8 +240,6 @@ sub payment_info {
'MasterCard' => 'MasterCard',
'Discover' => 'Discover card',
'American Express' => 'American Express card',
- 'Switch' => 'Switch',
- 'Solo' => 'Solo',
},
};
@@ -276,7 +288,7 @@ sub process_payment {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
my %return;
@@ -343,8 +355,7 @@ sub process_payment {
'payname' => $payname,
'paybatch' => $paybatch,
'paycvv' => $paycvv,
- map { $_ => $p->{$_} } qw( paystart_month paystart_year payissue payip
- address1 address2 city state zip )
+ map { $_ => $p->{$_} } qw( address1 address2 city state zip )
);
return { 'error' => $error } if $error;
@@ -353,8 +364,7 @@ sub process_payment {
if ( $p->{'save'} ) {
my $new = new FS::cust_main { $cust_main->hash };
$new->set( $_ => $p->{$_} )
- foreach qw( payname paystart_month paystart_year payissue payip
- address1 address2 city state zip payinfo );
+ foreach qw( payname address1 address2 city state zip payinfo );
$new->set( 'paydate' => $p->{'year'}. '-'. $p->{'month'}. '-01' );
$new->set( 'payby' => $p->{'auto'} ? 'CARD' : 'DCRD' );
my $error = $new->replace($cust_main);
@@ -366,39 +376,9 @@ sub process_payment {
}
-sub process_prepay {
-
- my $p = shift;
-
- my $session = _cache->get($p->{'session_id'})
- or return { 'error' => "Can't resume session" }; #better error message
-
- my %return;
-
- my $custnum = $session->{'custnum'};
-
- my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } )
- or return { 'error' => "unknown custnum $custnum" };
-
- my( $amount, $seconds ) = ( 0, 0 );
- my $error = $cust_main->recharge_prepay( $p->{'prepaid_cardnum'},
- \$amount,
- \$seconds
- );
-
- return { 'error' => $error } if $error;
-
- return { 'error' => '',
- 'amount' => $amount,
- 'seconds' => $seconds,
- 'duration' => duration_exact($seconds),
- };
-
-}
-
sub invoice {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
my $custnum = $session->{'custnum'};
@@ -420,7 +400,7 @@ sub invoice {
sub list_invoices {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
my $custnum = $session->{'custnum'};
@@ -441,7 +421,7 @@ sub list_invoices {
sub cancel {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
my $custnum = $session->{'custnum'};
@@ -494,7 +474,7 @@ sub list_pkgs {
} $cust_main->ncancelled_pkgs
],
'small_custview' =>
- small_custview( $cust_main, $conf->config('countrydefault') ),
+ small_custview( $cust_main, $conf->config('defaultcountry') ),
};
}
@@ -612,7 +592,7 @@ sub order_pkg {
sub cancel_pkg {
my $p = shift;
- my $session = _cache->get($p->{'session_id'})
+ my $session = $cache->get($p->{'session_id'})
or return { 'error' => "Can't resume session" }; #better error message
my $custnum = $session->{'custnum'};
@@ -737,7 +717,7 @@ sub part_svc_info {
'acstate' => '',
'small_custview' =>
- small_custview( $cust_main, $conf->config('countrydefault') ),
+ small_custview( $cust_main, $conf->config('defaultcountry') ),
};
@@ -767,7 +747,7 @@ sub unprovision_svc {
return { 'svc' => $cust_svc->part_svc->svc,
'error' => $cust_svc->cancel,
'small_custview' =>
- small_custview( $cust_main, $conf->config('countrydefault') ),
+ small_custview( $cust_main, $conf->config('defaultcountry') ),
};
}
@@ -781,27 +761,28 @@ sub _custoragent_session_custnum {
if ( $p->{'session_id'} ) {
$context = 'customer';
- $session = _cache->get($p->{'session_id'})
- or return ( 'error' => "Can't resume session" ); #better error message
+ $session = $cache->get($p->{'session_id'})
+ or return { 'error' => "Can't resume session" }; #better error message
$custnum = $session->{'custnum'};
} elsif ( $p->{'agent_session_id'} ) {
$context = 'agent';
- my $agent_cache = new FS::ClientAPI_SessionCache( {
+ my $agent_cache = new Cache::SharedMemoryCache( {
'namespace' => 'FS::ClientAPI::Agent',
} );
$session = $agent_cache->get($p->{'agent_session_id'})
- or return ( 'error' => "Can't resume session" ); #better error message
+ or return { 'error' => "Can't resume session" }; #better error message
$custnum = $p->{'custnum'};
} else {
- return ( 'error' => "Can't resume session" ); #better error message
+ return { 'error' => "Can't resume session" }; #better error message
}
($context, $session, $custnum);
}
+
1;
diff --git a/FS/FS/ClientAPI/Signup.pm b/FS/FS/ClientAPI/Signup.pm
index ed71651fa..dc627e9bd 100644
--- a/FS/FS/ClientAPI/Signup.pm
+++ b/FS/FS/ClientAPI/Signup.pm
@@ -5,7 +5,6 @@ use Tie::RefHash;
use FS::Conf;
use FS::Record qw(qsearch qsearchs dbdef);
use FS::Msgcat qw(gettext);
-use FS::ClientAPI_SessionCache;
use FS::agent;
use FS::cust_main_county;
use FS::part_pkg;
@@ -15,7 +14,12 @@ use FS::cust_pkg;
use FS::svc_acct;
use FS::acct_snarf;
use FS::queue;
-use FS::reg_code;
+
+use FS::ClientAPI; #hmm
+FS::ClientAPI->register_handlers(
+ 'Signup/signup_info' => \&signup_info,
+ 'Signup/new_customer' => \&new_customer,
+);
sub signup_info {
my $packet = shift;
@@ -89,7 +93,7 @@ sub signup_info {
my $session = '';
if ( exists $packet->{'session_id'} ) {
- my $cache = new FS::ClientAPI_SessionCache( {
+ my $cache = new Cache::SharedMemoryCache( {
'namespace' => 'FS::ClientAPI::Agent',
} );
$session = $cache->get($packet->{'session_id'});
@@ -101,22 +105,7 @@ sub signup_info {
}
$signup_info->{'part_pkg'} = [];
-
- if ( $packet->{'reg_code'} ) {
- $signup_info->{'part_pkg'} =
- [ map { { 'payby' => [ $_->payby ], %{$_->hashref} } }
- grep { $_->svcpart('svc_acct') }
- map { $_->part_pkg }
- qsearchs( 'reg_code', { 'code' => $packet->{'reg_code'},
- 'agentnum' => $agentnum, } )
-
- ];
-
- $signup_info->{'error'} = 'Unknown registration code'
- unless @{ $signup_info->{'part_pkg'} };
-
- } elsif ( $packet->{'promo_code'} ) {
-
+ if ( $packet->{'promo_code'} ) {
$signup_info->{'part_pkg'} =
[ map { { 'payby' => [ $_->payby ], %{$_->hashref} } }
grep { $_->svcpart('svc_acct') }
@@ -165,7 +154,7 @@ sub new_customer {
my $agentnum;
if ( exists $packet->{'session_id'} ) {
- my $cache = new FS::ClientAPI_SessionCache( {
+ my $cache = new Cache::SharedMemoryCache( {
'namespace' => 'FS::ClientAPI::Agent',
} );
my $session = $cache->get($packet->{'session_id'});
@@ -197,12 +186,7 @@ sub new_customer {
ship_city ship_county ship_state ship_zip ship_country
ship_daytime ship_night ship_fax
- payby
- payinfo paycvv paydate payname
- paystart_month paystart_year payissue
- payip
-
- referral_custnum comments
+ payby payinfo paycvv paydate payname referral_custnum comments
)
} );
@@ -225,18 +209,10 @@ sub new_customer {
or return { 'error' => "WARNING: unknown pkgpart: $pkgpart" };
my $svcpart = $part_pkg->svcpart('svc_acct');
- my $reg_code = '';
- if ( $packet->{'reg_code'} ) {
- $reg_code = qsearchs( 'reg_code', { 'code' => $packet->{'reg_code'},
- 'agentnum' => $agentnum, } )
- or return { 'error' => 'Unknown registration code' };
- }
-
my $cust_pkg = new FS::cust_pkg ( {
#later#'custnum' => $custnum,
'pkgpart' => $packet->{'pkgpart'},
'promo_code' => $packet->{'promo_code'},
- 'reg_code' => $packet->{'reg_code'},
} );
#my $error = $cust_pkg->check;
#return { 'error' => $error } if $error;
@@ -329,11 +305,6 @@ sub new_customer {
}
- if ( $reg_code ) {
- $error = $reg_code->delete;
- return { 'error' => $error } if $error;
- }
-
$error = $placeholder->delete;
return { 'error' => $error } if $error;
diff --git a/FS/FS/ClientAPI/passwd.pm b/FS/FS/ClientAPI/passwd.pm
index b22d7617e..cb839ecef 100644
--- a/FS/FS/ClientAPI/passwd.pm
+++ b/FS/FS/ClientAPI/passwd.pm
@@ -5,6 +5,13 @@ use FS::Record qw(qsearchs);
use FS::svc_acct;
use FS::svc_domain;
+use FS::ClientAPI; #hmm
+FS::ClientAPI->register_handlers(
+ 'passwd/passwd' => \&passwd,
+ 'passwd/chfn' => \&chfn,
+ 'passwd/chsh' => \&chsh,
+);
+
sub passwd {
my $packet = shift;
diff --git a/FS/FS/ClientAPI_SessionCache.pm b/FS/FS/ClientAPI_SessionCache.pm
deleted file mode 100644
index b722484ec..000000000
--- a/FS/FS/ClientAPI_SessionCache.pm
+++ /dev/null
@@ -1,78 +0,0 @@
-package FS::ClientAPI_SessionCache;
-
-use strict;
-use vars qw($module);
-use FS::UID qw(datasrc);
-
-#ask FS::UID to run this stuff for us later
-install_callback FS::UID sub {
- my $conf = new FS::Conf;
- $module = $conf->config('selfservice_server-cache_module')
- || 'Cache::SharedMemoryCache';
-};
-
-=head1 NAME
-
-FS::ClientAPI_SessionCache;
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-Minimal Cache::Cache-alike interface for storing session cache information.
-Backends to Cache::SharedMemoryCache, Cache::FileCache, or an internal
-implementation which stores information in the clientapi_session and
-clientapi_session_field database tables.
-
-=head1 METHODS
-
-=over 4
-
-=item new
-
-=cut
-
-sub new {
- my $proto = shift;
- my $class = ref($proto) || $proto;
- unless ( $module =~ /^_Database$/ ) {
- eval "use $module;";
- die $@ if $@;
- my $self = $module->new(@_);
- $self->set_cache_root('/usr/local/etc/freeside/clientapi_session.'.datasrc)
- if $module =~ /^Cache::FileCache$/;
- $self;
- } else {
- my $self = shift;
- bless ($self, $class);
- }
-}
-
-sub get {
- my($self, $session_id) = @_;
- die '_Database self-service session cache not yet implemented';
-}
-
-sub set {
- my($self, $session_id, $session, $expiration) = @_;
- die '_Database self-service session cache not yet implemented';
-}
-
-sub remove {
- my($self, $session_id) = @_;
- die '_Database self-service session cache not yet implemented';
-}
-
-=back
-
-=head1 BUGS
-
-Minimal documentation.
-
-=head1 SEE ALSO
-
-L<Cache::Cache>, L<FS::clientapi_session>, L<FS::clientapi_session_field>
-
-=cut
-
-1;
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index 88dbdf082..b6c115dc4 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -95,21 +95,6 @@ sub config {
}
}
-=item config_binary KEY
-
-Returns the exact scalar value for key.
-
-=cut
-
-sub config_binary {
- my($self,$file)=@_;
- my($dir)=$self->dir;
- my $fh = new IO::File "<$dir/$file" or return;
- local $/;
- my $content = <$fh>;
- $content;
-}
-
=item exists KEY
Returns true if the specified key exists, even if the corresponding value
@@ -224,31 +209,6 @@ sub config_items {
new FS::ConfItem {
'key' => $basename,
'section' => 'billing',
- 'description' => 'Alternate HTML template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
- 'type' => 'textarea',
- }
- } glob($self->dir. '/invoice_html_*')
- ),
- ( map {
- my $basename = basename($_);
- $basename =~ /^(.*)$/;
- $basename = $1;
- ($latexname = $basename ) =~ s/latex/html/;
- new FS::ConfItem {
- 'key' => $basename,
- 'section' => 'billing',
- 'description' => "Alternate Notes section for HTML invoices. Defaults to the same data in $latexname if not specified.",
- 'type' => 'textarea',
- }
- } glob($self->dir. '/invoice_htmlnotes_*')
- ),
- ( 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',
}
@@ -342,34 +302,6 @@ httemplate/docs/config.html
},
{
- 'key' => 'encryption',
- 'section' => 'billing',
- 'description' => 'Enable encryption of credit cards.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'encryptionmodule',
- 'section' => 'billing',
- 'description' => 'Use which module for encryption?',
- 'type' => 'text',
- },
-
- {
- 'key' => 'encryptionpublickey',
- 'section' => 'billing',
- 'description' => 'Your RSA Public Key - Required if Encryption is turned on.',
- 'type' => 'textarea',
- },
-
- {
- 'key' => 'encryptionprivatekey',
- 'section' => 'billing',
- 'description' => 'Your RSA Private Key - Including this will enable the "Bill Now" feature. However if the system is compromised, a hacker can use this key to decode the stored credit card information. This is generally not a good idea.',
- 'type' => 'textarea',
- },
-
- {
'key' => 'business-onlinepayment',
'section' => 'billing',
'description' => '<a href="http://search.cpan.org/search?mode=module&query=Business%3A%3AOnlinePayment">Business::OnlinePayment</a> support, at least three lines: processor, login, and password. An optional fourth line specifies the action or actions (multiple actions are separated with `,\': for example: `Authorization Only, Post Authorization\'). Optional additional lines are passed to Business::OnlinePayment as %processor_options.',
@@ -391,13 +323,6 @@ httemplate/docs/config.html
},
{
- 'key' => 'business-onlinepayment-email-override',
- 'section' => 'billing',
- 'description' => 'Email address used instead of customer email address when submitting a BOP transaction.',
- 'type' => 'text',
- },
-
- {
'key' => 'bsdshellmachines',
'section' => 'deprecated',
'description' => '<b>DEPRECATED</b>, add a <i>bsdshell</i> <a href="../browse/part_export.cgi">export</a> instead. Your BSD flavored shell (and mail) machines, one per line. This enables export of `/etc/passwd\' and `/etc/master.passwd\'.',
@@ -512,7 +437,7 @@ httemplate/docs/config.html
{
'key' => 'erpcdmachines',
'section' => 'deprecated',
- 'description' => '<b>DEPRECATED</b>, ERPCD is no longer supported. Used to be ERPCD authentication machines, one per line. This enables export of `/usr/annex/acp_passwd\' and `/usr/annex/acp_dialup\'',
+ 'description' => '<b>DEPRECATED</b>, ERPCD is no longer supported. Used to be ERPCD authenticaion machines, one per line. This enables export of `/usr/annex/acp_passwd\' and `/usr/annex/acp_dialup\'',
'type' => 'textarea',
},
@@ -580,38 +505,9 @@ httemplate/docs/config.html
},
{
- 'key' => 'invoice_html',
- 'section' => 'billing',
- 'description' => 'Optional HTML template for invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
-
- 'type' => 'textarea',
- },
-
- {
- 'key' => 'invoice_htmlnotes',
- 'section' => 'billing',
- 'description' => 'Notes section for HTML invoices. Defaults to the same data in invoice_latexnotes if not specified.',
- 'type' => 'textarea',
- },
-
- {
- 'key' => 'invoice_htmlfooter',
- 'section' => 'billing',
- 'description' => 'Footer for HTML invoices. Defaults to the same data in invoice_latexfooter if not specified.',
- 'type' => 'textarea',
- },
-
- {
- 'key' => 'invoice_htmlreturnaddress',
- 'section' => 'billing',
- 'description' => 'Return address for HTML invoices. Defaults to the same data in invoice_latexreturnaddress if not specified.',
- 'type' => 'textarea',
- },
-
- {
'key' => 'invoice_latex',
'section' => 'billing',
- 'description' => 'Optional LaTeX template for typeset PostScript invoices. See the <a href="../docs/billing.html">billing documentation</a> for details.',
+ 'description' => 'Optional LaTeX template for typeset PostScript invoices.',
'type' => 'textarea',
},
@@ -630,34 +526,12 @@ httemplate/docs/config.html
},
{
- 'key' => 'invoice_latexreturnaddress',
- 'section' => 'billing',
- 'description' => 'Return address 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_email_pdf',
- 'section' => 'billing',
- 'description' => 'Send PDF invoice as an attachment to emailed invoices. By default, includes the plain text invoice as the email body, unless invoice_email_pdf_note is set.',
- 'type' => 'checkbox'
- },
-
- {
- 'key' => 'invoice_email_pdf_note',
- 'section' => 'billing',
- 'description' => 'If defined, this text will replace the default plain text invoice as the body of emailed PDF invoices.',
- 'type' => 'textarea'
- },
-
-
{
'key' => 'invoice_default_terms',
'section' => 'billing',
@@ -668,7 +542,7 @@ httemplate/docs/config.html
{
'key' => 'invoice_send_receipts',
- 'section' => 'deprecated',
+ 'section' => 'deprecated',q
'description' => '<b>DEPRECATED</b>, this used to send an invoice copy on payments and credits. See the payment_receipt_email and XXXX instead.',
'type' => 'checkbox',
},
@@ -676,7 +550,7 @@ httemplate/docs/config.html
{
'key' => 'payment_receipt_email',
'section' => 'billing',
- 'description' => 'Template file for payment receipts. Payment receipts are sent to the customer email invoice destination(s) when a payment is received. See the <a href="http://search.cpan.org/~mjd/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <ul><li><code>$date</code> <li><code>$name</code> <li><code>$paynum</code> - Freeside payment number <li><code>$paid</code> - Amount of payment <li><code>$payby</code> - Payment type (Card, Check, Electronic check, etc.) <li><code>$payinfo</code> - Masked credit card number or check number <li><code>$balance</code> - New balance</ul>',
+ 'description' => 'Template file for payment receipts.',
'type' => 'textarea',
},
@@ -723,7 +597,7 @@ httemplate/docs/config.html
'editlist_parts' => [ { type=>'text' },
{ type=>'immutable', value=>'IN' },
{ type=>'select',
- select_enum=>{ map { $_=>$_ } qw(A CNAME MX NS TXT)} },
+ select_enum=>{ map { $_=>$_ } qw(A CNAME MX NS)} },
{ type=> 'text' }, ],
},
@@ -1050,13 +924,6 @@ httemplate/docs/config.html
'type' => 'checkbox',
},
- {
- 'key' => 'username-percent',
- 'section' => 'username',
- 'description' => 'Allow the percent character (%) in usernames.',
- 'type' => 'checkbox',
- },
-
{
'key' => 'username_policy',
'section' => 'deprecated',
@@ -1202,13 +1069,6 @@ httemplate/docs/config.html
},
{
- 'key' => 'backend-realtime',
- 'section' => '',
- 'description' => 'Run billing for backend signups immediately.',
- 'type' => 'checkbox',
- },
-
- {
'key' => 'declinetemplate',
'section' => 'billing',
'description' => 'Template file for credit card decline emails.',
@@ -1265,16 +1125,9 @@ httemplate/docs/config.html
},
{
- 'key' => 'require_taxclasses',
- 'section' => 'billing',
- 'description' => 'Require a taxclass to be entered for every package',
- 'type' => 'checkbox',
- },
-
- {
'key' => 'welcome_email',
'section' => '',
- 'description' => 'Template file for welcome email. Welcome emails are sent to the customer email invoice destination(s) each time a svc_acct record is created. See the <a href="http://search.cpan.org/~mjd/Text-Template/lib/Text/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available<ul><li><code>$username</code> <li><code>$password</code> <li><code>$first</code> <li><code>$last</code> <li><code>$pkg</code></ul>',
+ 'description' => 'Template file for welcome email. Welcome emails are sent to the customer email invoice destination(s) each time a svc_acct record is created. See the <a href="http://search.cpan.org/doc/MJD/Text-Template-1.42/Template.pm">Text::Template</a> documentation for details on the template substitution language. The following variables are available: <code>$username</code>, <code>$password</code>, <code>$first</code>, <code>$last</code> and <code>$pkg</code>.',
'type' => 'textarea',
},
@@ -1301,19 +1154,11 @@ httemplate/docs/config.html
},
{
- 'key' => 'payby',
- 'section' => 'billing',
- 'description' => 'Available payment types.',
- 'type' => 'selectmultiple',
- 'select_enum' => [ qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP) ],
- },
-
- {
'key' => 'payby-default',
'section' => 'UI',
'description' => 'Default payment type. HIDE disables display of billing information and sets customers to BILL.',
'type' => 'select',
- 'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL CASH WEST MCRD COMP HIDE) ],
+ 'select_enum' => [ '', qw(CARD DCRD CHEK DCHK LECB BILL COMP HIDE) ],
},
{
@@ -1478,37 +1323,16 @@ httemplate/docs/config.html
{
'key' => 'ticket_system',
'section' => '',
- 'description' => 'Ticketing system integration. <b>RT_Internal</b> uses the built-in RT ticketing system (see the <a href="../docs/install-rt">integrated ticketing installation instructions</a>). <b>RT_External</b> accesses an external RT installation in a separate database (local or remote).',
+ 'description' => 'Ticketing system integraiton. <b>RT_Internal</b> uses the built-in RT ticketing system (use <code>make create-rt</code> to create the necessary tables). <b>RT_Libs</b> uses the built-in RT libraries to access an RT installation in a separate database (local or remote). <b>RT_External</b> uses RT\'s XML interface and RTx::Atom to access an RT installation in a separate database (local or remote).',
'type' => 'select',
- #'select_enum' => [ '', qw(RT_Internal RT_Libs RT_External) ],
- 'select_enum' => [ '', qw(RT_Internal RT_External) ],
+ 'select_enum' => [ '', qw(RT_Internal RT_Libs RT_External) ],
},
{
'key' => 'ticket_system-default_queueid',
'section' => '',
- 'description' => 'Default queue used when creating new customer tickets.',
- 'type' => 'select-sub',
- 'options_sub' => sub {
- my $conf = new FS::Conf;
- if ( $conf->config('ticket_system') ) {
- eval "use FS::TicketSystem;";
- die $@ if $@;
- FS::TicketSystem->queues();
- } else {
- ();
- }
- },
- 'option_sub' => sub {
- my $conf = new FS::Conf;
- if ( $conf->config('ticket_system') ) {
- eval "use FS::TicketSystem;";
- die $@ if $@;
- FS::TicketSystem->queue(shift);
- } else {
- '';
- }
- },
+ 'description' => 'Default queue number used when creating new customer tickets.',
+ 'type' => 'text',
},
{
@@ -1533,21 +1357,6 @@ httemplate/docs/config.html
},
{
- 'key' => 'ticket_system-rt_external_datasrc',
- 'section' => '',
- 'description' => 'With external RT integration, the DBI data source for the external RT installation, for example, <code>DBI:Pg:user=rt_user;password=rt_word;host=rt.example.com;dbname=rt</code>',
- 'type' => 'text',
-
- },
-
- {
- 'key' => 'ticket_system-rt_external_url',
- 'section' => '',
- 'description' => 'With external RT integration, the URL for the external RT installation, for example, <code>https://rt.example.com/rt</code>',
- 'type' => 'text',
- },
-
- {
'key' => 'company_name',
'section' => 'required',
'description' => 'Your company name',
@@ -1562,105 +1371,12 @@ httemplate/docs/config.html
},
{
- 'key' => 'cc-void',
- 'section' => 'billing',
- 'description' => 'Enable local-only voiding of credit card payments in addition to refunds against the payment gateway',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'unvoid',
- 'section' => 'billing',
- 'description' => 'Enable unvoiding of voided payments',
- 'type' => 'checkbox',
- },
-
- {
'key' => 'address2-search',
'section' => 'UI',
'description' => 'Enable a "Unit" search box which searches the second address field',
'type' => 'checkbox',
},
- { 'key' => 'referral_credit',
- 'section' => 'billing',
- 'description' => "Enables one-time referral credits in the amount of one month <i>referred</i> customer's recurring fee (irregardless of frequency).",
- 'type' => 'checkbox',
- },
-
- { 'key' => 'selfservice_server-cache_module',
- 'section' => '',
- 'description' => 'Module used to store self-service session information. All modules handle any number of self-service servers. Cache::SharedMemoryCache is appropriate for a single database / single Freeside server. Cache::FileCache is useful for multiple databases on a single server, or when IPC::ShareLite is not available (i.e. FreeBSD).', # _Database stores session information in the database and is appropriate for multiple Freeside servers, but may be slower.',
- 'type' => 'select',
- 'select_enum' => [ 'Cache::SharedMemoryCache', 'Cache::FileCache', ], # '_Database' ],
- },
-
- {
- 'key' => 'hylafax',
- 'section' => '',
- 'description' => 'Options for a HylaFAX server to enable the FAX invoice destination. They should be in the form of a space separated list of arguments to the Fax::Hylafax::Client::sendfax subroutine. You probably shouldn\'t override things like \'docfile\'. *Note* Only supported when using typeset invoices (see the invoice_latex configuration option).',
- 'type' => [qw( checkbox textarea )],
- },
-
- {
- 'key' => 'svc_acct-usage_suspend',
- 'section' => 'billing',
- 'description' => 'Suspends the package an account belongs to when svc_acct.seconds is decremented to 0 or below (accounts with an empty seconds value are ignored). Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'svc_acct-usage_unsuspend',
- 'section' => 'billing',
- 'description' => 'Unuspends the package an account belongs to when svc_acct.seconds is incremented from 0 or below to a positive value (accounts with an empty seconds value are ignored). Typically used in conjunction with prepaid packages and freeside-sqlradius-radacctd.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'cust-fields',
- 'section' => 'UI',
- 'description' => 'Which customer fields to display on reports',
- 'type' => 'select',
- 'select_enum' => [
- 'Customer: Last, First</b> or</i> Company (Last, First)</b>',
- 'Cust# | Customer: custnum | Last, First or Company (Last, First)',
- 'Name | Company: Last, First | Company',
- 'Cust# | Name | Company: custnum | Last, First | Company',
- '(bill) Customer | (service) Customer: Last, First or Company (Last, First) | (same for service address if present)',
- 'Cust# | (bill) Customer | (service) Customer: custnum | Last, First or Company (Last, First) | (same for service address if present)',
- '(bill) Name | (bill) Company | (service) Name | (service) Company: Last, First | Company | (same for service address if present)',
- 'Cust# | (bill) Name | (bill) Company | (service) Name | (service) Company: custnum | Last, First | Company | (same for service address if present)',
- ],
- },
-
- {
- 'key' => 'cust_pkg-display_times',
- 'section' => 'UI',
- 'description' => 'Display full timestamps (not just dates) for customer packages. Useful if you are doing real-time things like hourly prepaid.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'svc_acct-edit_uid',
- 'section' => 'shell',
- 'description' => 'Allow UID editing.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'svc_acct-edit_gid',
- 'section' => 'shell',
- 'description' => 'Allow GID editing.',
- 'type' => 'checkbox',
- },
-
- {
- 'key' => 'zone-underscore',
- 'section' => 'BIND',
- 'description' => 'Allow underscores in zone names. As underscores are illegal characters in zone names, this option is not recommended.',
- 'type' => 'checkbox',
- },
-
);
1;
diff --git a/FS/FS/ConfItem.pm b/FS/FS/ConfItem.pm
index a0e997ac7..83295b4fa 100644
--- a/FS/FS/ConfItem.pm
+++ b/FS/FS/ConfItem.pm
@@ -2,7 +2,7 @@ package FS::ConfItem;
=head1 NAME
-FS::ConfItem - Configuration option meta-data.
+FS::ConfItem - Configutaion option meta-data.
=head1 SYNOPSIS
diff --git a/FS/FS/Daemon.pm b/FS/FS/Daemon.pm
deleted file mode 100644
index 3e64f79e9..000000000
--- a/FS/FS/Daemon.pm
+++ /dev/null
@@ -1,91 +0,0 @@
-package FS::Daemon;
-
-use vars qw( @ISA @EXPORT_OK );
-use vars qw( $pid_dir $me $pid_file $sigint $sigterm $logfile );
-use Exporter;
-use Fcntl qw(:flock);
-use POSIX qw(setsid);
-use Date::Format;
-
-#this is a simple refactoring of the stuff from freeside-queued, just to
-#avoid duplicate code. eventually this should use something from CPAN.
-
-@ISA = qw(Exporter);
-@EXPORT_OK = qw( daemonize1 drop_root daemonize2 sigint sigterm logfile );
-
-$pid_dir = '/var/run';
-
-sub daemonize1 {
- $me = shift;
-
- $pid_file = "$pid_dir/$me";
- $pid_file .= '.'.shift if scalar(@_);
- $pid_file .= '.pid';
-
- chdir "/" or die "Can't chdir to /: $!";
- open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
- defined(my $pid = fork) or die "Can't fork: $!";
- if ( $pid ) {
- print "$me started with pid $pid\n"; #logging to $log_file\n";
- exit unless $pid_file;
- my $pidfh = new IO::File ">$pid_file" or exit;
- print $pidfh "$pid\n";
- exit;
- }
-
- #sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; $kids--; }
- #$SIG{CHLD} = \&REAPER;
- $sigterm = 0;
- $sigint = 0;
- $SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; };
- $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
-}
-
-sub drop_root {
- my $freeside_gid = scalar(getgrnam('freeside'))
- or die "can't find freeside group\n";
- $) = $freeside_gid;
- $( = $freeside_gid;
- #if freebsd can't setuid(), presumably it can't setgid() either. grr fleabsd
- ($(,$)) = ($),$();
- $) = $freeside_gid;
-
- $> = $FS::UID::freeside_uid;
- $< = $FS::UID::freeside_uid;
- #freebsd is sofa king broken, won't setuid()
- ($<,$>) = ($>,$<);
- $> = $FS::UID::freeside_uid;
-}
-
-sub daemonize2 {
- open STDOUT, '>/dev/null' or die "Can't write to /dev/null: $!";
- setsid or die "Can't start a new session: $!";
- open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
-
- $SIG{__DIE__} = \&_die;
- $SIG{__WARN__} = \&_logmsg;
-
- warn "$me starting\n";
-}
-
-sub sigint { $sigint; }
-sub sigterm { $sigterm; }
-
-sub logfile { $logfile = shift; } #_logmsg('test'); }
-
-sub _die {
- my $msg = shift;
- unlink $pid_file if -e $pid_file;
- _logmsg($msg);
-}
-
-sub _logmsg {
- chomp( my $msg = shift );
- my $log = new IO::File ">>$logfile";
- flock($log, LOCK_EX);
- seek($log, 0, 2);
- print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
- flock($log, LOCK_UN);
- close $log;
-}
-
diff --git a/FS/FS/Misc.pm b/FS/FS/Misc.pm
index 2e383d549..df9717068 100644
--- a/FS/FS/Misc.pm
+++ b/FS/FS/Misc.pm
@@ -1,15 +1,11 @@
package FS::Misc;
use strict;
-use vars qw ( @ISA @EXPORT_OK $DEBUG );
+use vars qw ( @ISA @EXPORT_OK );
use Exporter;
-use Carp;
-use Data::Dumper;
@ISA = qw( Exporter );
-@EXPORT_OK = qw( send_email send_fax );
-
-$DEBUG = 0;
+@EXPORT_OK = qw( send_email );
=head1 NAME
@@ -41,19 +37,9 @@ I<to> - (required) comma-separated scalar or arrayref of recipients
I<subject> - (required)
-I<content-type> - (optional) MIME type for the body
-
-I<body> - (required unless I<nobody> is true) arrayref of body text lines
-
-I<mimeparts> - (optional, but required if I<nobody> is true) arrayref of MIME::Entity->build PARAMHASH refs or MIME::Entity objects. These will be passed as arguments to MIME::Entity->attach().
-
-I<nobody> - (optional) when set true, send_email will ignore the I<body> option and simply construct a message with the given I<mimeparts>. In this case,
-I<content-type>, if specified, overrides the default "multipart/mixed" for the outermost MIME container.
+I<content-type> - (optional) MIME type
-I<content-encoding> - (optional) when using nobody, optional top-level MIME
-encoding which, if specified, overrides the default "7bit".
-
-I<type> - (optional) type parameter for multipart/related messages
+I<body> - (required) arrayref of body text lines
=cut
@@ -61,7 +47,6 @@ use vars qw( $conf );
use Date::Format;
use Mail::Header;
use Mail::Internet 1.44;
-use MIME::Entity;
use FS::UID;
FS::UID->install_callback( sub {
@@ -70,111 +55,25 @@ FS::UID->install_callback( sub {
sub send_email {
my(%options) = @_;
- if ( $DEBUG ) {
- my %doptions = %options;
- $doptions{'body'} = '(full body not shown in debug)';
- warn "FS::Misc::send_email called with options:\n ". Dumper(\%doptions);
-# join("\n", map { " $_: ". $options{$_} } keys %options ). "\n"
- }
$ENV{MAILADDRESS} = $options{'from'};
my $to = ref($options{to}) ? join(', ', @{ $options{to} } ) : $options{to};
-
- my @mimeargs = ();
- my @mimeparts = ();
- if ( $options{'nobody'} ) {
-
- croak "'mimeparts' option required when 'nobody' option given\n"
- unless $options{'mimeparts'};
-
- @mimeparts = @{$options{'mimeparts'}};
-
- @mimeargs = (
- 'Type' => ( $options{'content-type'} || 'multipart/mixed' ),
- 'Encoding' => ( $options{'content-encoding'} || '7bit' ),
- );
-
- } else {
-
- @mimeparts = @{$options{'mimeparts'}}
- if ref($options{'mimeparts'}) eq 'ARRAY';
-
- if (scalar(@mimeparts)) {
-
- @mimeargs = (
- 'Type' => 'multipart/mixed',
- 'Encoding' => '7bit',
- );
-
- unshift @mimeparts, {
- 'Type' => ( $options{'content-type'} || 'text/plain' ),
- 'Data' => $options{'body'},
- 'Encoding' => ( $options{'content-type'} ? '-SUGGEST' : '7bit' ),
- 'Disposition' => 'inline',
- };
-
- } else {
-
- @mimeargs = (
- 'Type' => ( $options{'content-type'} || 'text/plain' ),
- 'Data' => $options{'body'},
- 'Encoding' => ( $options{'content-type'} ? '-SUGGEST' : '7bit' ),
- );
-
- }
-
- }
-
- my $domain;
- if ( $options{'from'} =~ /\@([\w\.\-]+)/ ) {
- $domain = $1;
- } else {
- warn 'no domain found in invoice from address '. $options{'from'}.
- '; constructing Message-ID @example.com';
- $domain = 'example.com';
- }
- my $message_id = join('.', rand()*(2**32), $$, time). "\@$domain";
-
- my $message = MIME::Entity->build(
- 'From' => $options{'from'},
- 'To' => $to,
- 'Sender' => $options{'from'},
- 'Reply-To' => $options{'from'},
- 'Date' => time2str("%a, %d %b %Y %X %z", time),
- 'Subject' => $options{'subject'},
- 'Message-ID' => "<$message_id>",
- @mimeargs,
+ my @header = (
+ 'From: '. $options{'from'},
+ 'To: '. $to,
+ 'Sender: '. $options{'from'},
+ 'Reply-To: '. $options{'from'},
+ 'Date: '. time2str("%a, %d %b %Y %X %z", time),
+ 'Subject: '. $options{'subject'},
);
+ push @header, 'Content-Type: '. $options{'content-type'}
+ if exists($options{'content-type'});
+ my $header = new Mail::Header ( \@header );
- if ( $options{'type'} ) {
- #false laziness w/cust_bill::generate_email
- $message->head->replace('Content-type',
- $message->mime_type.
- '; boundary="'. $message->head->multipart_boundary. '"'.
- '; type='. $options{'type'}
- );
- }
-
- foreach my $part (@mimeparts) {
-
- if ( UNIVERSAL::isa($part, 'MIME::Entity') ) {
-
- warn "attaching MIME part from MIME::Entity object\n"
- if $DEBUG;
- $message->add_part($part);
-
- } elsif ( ref($part) eq 'HASH' ) {
-
- warn "attaching MIME part from hashref:\n".
- join("\n", map " $_: ".$part->{$_}, keys %$part ). "\n"
- if $DEBUG;
- $message->attach(%$part);
-
- } else {
- croak "mimepart $part isn't a hashref or MIME::Entity object!";
- }
-
- }
+ my $message = new Mail::Internet (
+ 'Header' => $header,
+ 'Body' => $options{'body'},
+ );
my $smtpmachine = $conf->config('smtpmachine');
$!=0;
@@ -185,89 +84,6 @@ sub send_email {
}
-=item send_fax OPTION => VALUE ...
-
-Options:
-
-I<dialstring> - (required) 10-digit phone number w/ area code
-
-I<docdata> - (required) Array ref containing PostScript or TIFF Class F document
-
--or-
-
-I<docfile> - (required) Filename of PostScript TIFF Class F document
-
-...any other options will be passed to L<Fax::Hylafax::Client::sendfax>
-
-
-=cut
-
-sub send_fax {
-
- my %options = @_;
-
- die 'HylaFAX support has not been configured.'
- unless $conf->exists('hylafax');
-
- eval {
- require Fax::Hylafax::Client;
- };
-
- if ($@) {
- if ($@ =~ /^Can't locate Fax.*/) {
- die "You must have Fax::Hylafax::Client installed to use invoice faxing."
- } else {
- die $@;
- }
- }
-
- my %hylafax_opts = map { split /\s+/ } $conf->config('hylafax');
-
- die 'Called send_fax without a \'dialstring\'.'
- unless exists($options{'dialstring'});
-
- if (exists($options{'docdata'}) and ref($options{'docdata'}) eq 'ARRAY') {
- my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
- my $fh = new File::Temp(
- TEMPLATE => 'faxdoc.'. $options{'dialstring'} . '.XXXXXXXX',
- DIR => $dir,
- UNLINK => 0,
- ) or die "can't open temp file: $!\n";
-
- $options{docfile} = $fh->filename;
-
- print $fh @{$options{'docdata'}};
- close $fh;
-
- delete $options{'docdata'};
- }
-
- die 'Called send_fax without a \'docfile\' or \'docdata\'.'
- unless exists($options{'docfile'});
-
- #FIXME: Need to send canonical dialstring to HylaFAX, but this only
- # works in the US.
-
- $options{'dialstring'} =~ s/[^\d\+]//g;
- if ($options{'dialstring'} =~ /^\d{10}$/) {
- $options{dialstring} = '+1' . $options{'dialstring'};
- } else {
- return 'Invalid dialstring ' . $options{'dialstring'} . '.';
- }
-
- my $faxjob = &Fax::Hylafax::Client::sendfax(%options, %hylafax_opts);
-
- if ($faxjob->success) {
- warn "Successfully queued fax to '$options{dialstring}' with jobid " .
- $faxjob->jobid
- if $DEBUG;
- return '';
- } else {
- return 'Error while sending FAX: ' . $faxjob->trace;
- }
-
-}
-
package Mail::Internet;
use Mail::Address;
@@ -322,9 +138,6 @@ sub Mail::Internet::mysmtpsend {
# Send it
- #warn "Headers: \n" . join('',@{$hdr->header});
- #warn "Body: \n" . join('',@{$src->body});
-
my $ok = $smtp->mail( $envelope ) &&
$smtp->to(@addr) &&
$smtp->data(join("", @{$hdr->header},"\n",@{$src->body}));
@@ -340,8 +153,6 @@ sub Mail::Internet::mysmtpsend {
}
package FS::Misc;
-=back
-
=head1 BUGS
This package exists.
@@ -350,8 +161,6 @@ This package exists.
L<FS::UID>, L<FS::CGI>, L<FS::Record>, the base documentation.
-L<Fax::Hylafax::Client>
-
=cut
1;
diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm
index 887c8dcd4..cf0ac3b2f 100644
--- a/FS/FS/Record.pm
+++ b/FS/FS/Record.pm
@@ -1,44 +1,35 @@
package FS::Record;
use strict;
-use vars qw( $AUTOLOAD @ISA @EXPORT_OK $DEBUG
- $me %virtual_fields_cache $nowarn_identical );
+use vars qw( $dbdef_file $dbdef $setup_hack $AUTOLOAD @ISA @EXPORT_OK $DEBUG
+ $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.25;
+use DBIx::DBSchema 0.23;
use FS::UID qw(dbh getotaker datasrc driver_name);
-use FS::Schema qw(dbdef);
use FS::SearchCache;
use FS::Msgcat qw(gettext);
-use FS::Conf;
use FS::part_virtual_field;
use Tie::IxHash;
@ISA = qw(Exporter);
-
-#export dbdef for now... everything else expects to find it here
@EXPORT_OK = qw(dbh fields hfields qsearch qsearchs dbdef jsearch);
$DEBUG = 0;
$me = '[FS::Record]';
-$nowarn_identical = 0;
-
-my $conf;
-my $rsa_module;
-my $rsa_loaded;
-my $rsa_encrypt;
-my $rsa_decrypt;
-
-FS::UID->install_callback( sub {
- $conf = new FS::Conf;
+#ask FS::UID to run this stuff for us later
+$FS::UID::callback{'FS::Record'} = sub {
$File::CounterFile::DEFAULT_DIR = "/usr/local/etc/freeside/counters.". datasrc;
-} );
+ $dbdef_file = "/usr/local/etc/freeside/dbdef.". datasrc;
+ &reload_dbdef unless $setup_hack; #$setup_hack needed now?
+};
=head1 NAME
@@ -47,7 +38,7 @@ FS::Record - Database record objects
=head1 SYNOPSIS
use FS::Record;
- use FS::Record qw(dbh fields qsearch qsearchs);
+ use FS::Record qw(dbh fields qsearch qsearchs dbdef);
$record = new FS::Record 'table', \%hash;
$record = new FS::Record 'table', { 'column' => 'value', ... };
@@ -93,6 +84,10 @@ FS::Record - Database record objects
$error = $record->ut_anything('column');
$error = $record->ut_name('column');
+ $dbdef = reload_dbdef;
+ $dbdef = reload_dbdef "/non/standard/filename";
+ $dbdef = dbdef;
+
$quoted_value = _quote($value,'table','field');
#deprecated
@@ -185,36 +180,13 @@ sub create {
}
}
-=item qsearch PARAMS_HASHREF | TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, ADDL_FROM
+=item qsearch TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, AS
Searches the database for all records matching (at least) the key/value pairs
in HASHREF. Returns all the records found as `FS::TABLE' objects if that
module is loaded (i.e. via `use FS::cust_main;'), otherwise returns FS::Record
objects.
-The preferred usage is to pass a hash reference of named parameters:
-
- my @records = qsearch( {
- 'table' => 'table_name',
- 'hashref' => { 'field' => 'value'
- 'field' => { 'op' => '<',
- 'value' => '420',
- },
- },
-
- #these are optional...
- 'select' => '*',
- 'extra_sql' => 'AND field ',
- #'cache_obj' => '', #optional
- 'addl_from' => 'LEFT JOIN othtable USING ( field )',
- }
- );
-
-Much code still uses old-style positional parameters, this is also probably
-fine in the common case where there are only two parameters:
-
- my @records = qsearch( 'table', { 'field' => 'value' } );
-
###oops, argh, FS::Record::new only lets us create database fields.
#Normal behaviour if SELECT is not specified is `*', as in
#C<SELECT * FROM table WHERE ...>. However, there is an experimental new
@@ -227,28 +199,16 @@ fine in the common case where there are only two parameters:
=cut
sub qsearch {
- my($stable, $record, $select, $extra_sql, $cache, $addl_from );
- if ( ref($_[0]) ) { #hashref for now, eventually maybe accept a list too
- my $opt = shift;
- $stable = $opt->{'table'} or die "table name is required";
- $record = $opt->{'hashref'} || {};
- $select = $opt->{'select'} || '*';
- $extra_sql = $opt->{'extra_sql'} || '';
- $cache = $opt->{'cache_obj'} || '';
- $addl_from = $opt->{'addl_from'} || '';
- } else {
- ($stable, $record, $select, $extra_sql, $cache, $addl_from ) = @_;
- $select ||= '*';
- }
-
+ my($stable, $record, $select, $extra_sql, $cache, $as ) = @_;
#$stable =~ /^([\w\_]+)$/ or die "Illegal table: $table";
#for jsearch
$stable =~ /^([\w\s\(\)\.\,\=]+)$/ or die "Illegal table: $stable";
$stable = $1;
+ $select ||= '*';
my $dbh = dbh;
my $table = $cache ? $cache->table : $stable;
- my $dbdef_table = dbdef->table($table)
+ my $dbdef_table = $dbdef->table($table)
or die "No schema for table $table found - ".
"do you need to create it or run dbdef-create?";
my $pkey = $dbdef_table->primary_key;
@@ -263,7 +223,7 @@ sub qsearch {
}
my $statement = "SELECT $select FROM $stable";
- $statement .= " $addl_from" if $addl_from;
+ $statement .= " AS $as" if $as;
if ( @real_fields or @virtual_fields ) {
$statement .= ' WHERE '. join(' AND ',
( map {
@@ -284,7 +244,7 @@ sub qsearch {
if ( ! defined( $record->{$_} ) || $record->{$_} eq '' ) {
if ( $op eq '=' ) {
if ( driver_name eq 'Pg' ) {
- my $type = dbdef->table($table)->column($column)->type;
+ my $type = $dbdef->table($table)->column($column)->type;
if ( $type =~ /(int|serial)/i ) {
qq-( $column IS NULL )-;
} else {
@@ -295,7 +255,7 @@ sub qsearch {
}
} elsif ( $op eq '!=' ) {
if ( driver_name eq 'Pg' ) {
- my $type = dbdef->table($table)->column($column)->type;
+ my $type = $dbdef->table($table)->column($column)->type;
if ( $type =~ /(int|serial)/i ) {
qq-( $column IS NOT NULL )-;
} else {
@@ -365,7 +325,7 @@ sub qsearch {
grep defined( $record->{$_} ) && $record->{$_} ne '', @real_fields
) {
if ( $record->{$field} =~ /^\d+(\.\d+)?$/
- && dbdef->table($table)->column($field)->type =~ /(int|serial)/i
+ && $dbdef->table($table)->column($field)->type =~ /(int|serial)/i
) {
$sth->bind_param($bind++, $record->{$field}, { TYPE => SQL_INTEGER } );
} else {
@@ -419,71 +379,32 @@ sub qsearch {
}
}
}
- my @return;
+
if ( eval 'scalar(@FS::'. $table. '::ISA);' ) {
if ( eval 'FS::'. $table. '->can(\'new\')' eq \&new ) {
#derivied class didn't override new method, so this optimization is safe
if ( $cache ) {
- @return = map {
+ map {
new_or_cached( "FS::$table", { %{$_} }, $cache )
} values(%result);
} else {
- @return = map {
+ map {
new( "FS::$table", { %{$_} } )
} values(%result);
}
} else {
- #okay, its been tested
- # warn "untested code (class FS::$table uses custom new method)";
- @return = map {
+ warn "untested code (class FS::$table uses custom new method)";
+ map {
eval 'FS::'. $table. '->new( { %{$_} } )';
} values(%result);
}
-
- # Check for encrypted fields and decrypt them.
- if ($conf->exists('encryption') && eval 'defined(@FS::'. $table . '::encrypted_fields)') {
- foreach my $record (@return) {
- foreach my $field (eval '@FS::'. $table . '::encrypted_fields') {
- # Set it directly... This may cause a problem in the future...
- $record->setfield($field, $record->decrypt($record->getfield($field)));
- }
- }
- }
} else {
cluck "warning: FS::$table not loaded; returning FS::Record objects";
- @return = map {
+ map {
FS::Record->new( $table, { %{$_} } );
} values(%result);
}
- return @return;
-}
-
-=item by_key PRIMARY_KEY_VALUE
-
-This is a class method that returns the record with the given primary key
-value. This method is only useful in FS::Record subclasses. For example:
-
- my $cust_main = FS::cust_main->by_key(1); # retrieve customer with custnum 1
-
-is equivalent to:
-
- my $cust_main = qsearchs('cust_main', { 'custnum' => 1 } );
-
-=cut
-
-sub by_key {
- my ($class, $pkey_value) = @_;
- my $table = $class->table
- or croak "No table for $class found";
-
- my $dbdef_table = dbdef->table($table)
- or die "No schema for table $table found - ".
- "do you need to create it or run dbdef-create?";
- my $pkey = $dbdef_table->primary_key
- or die "No primary key for table $table";
-
- return qsearchs($table, { $pkey => $pkey_value });
}
=item jsearch TABLE, HASHREF, SELECT, EXTRA_SQL, PRIMARY_TABLE, PRIMARY_KEY
@@ -507,7 +428,7 @@ sub jsearch {
);
}
-=item qsearchs PARAMS_HASHREF | TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, ADDL_FROM
+=item qsearchs TABLE, HASHREF
Same as qsearch, except that if more than one record matches, it B<carp>s but
returns the first. If this happens, you either made a logic error in asking
@@ -518,7 +439,7 @@ for a single item, or your data is corrupted.
sub qsearchs { # $result_record = &FS::Record:qsearchs('table',\%hash);
my $table = $_[0];
my(@result) = qsearch(@_);
- cluck "warning: Multiple records in scalar search ($table)"
+ carp "warning: Multiple records in scalar search ($table)"
if scalar(@result) > 1;
#should warn more vehemently if the search was on a primary key?
scalar(@result) ? ($result[0]) : ();
@@ -551,7 +472,7 @@ Returns the DBIx::DBSchema::Table object for the table.
sub dbdef_table {
my($self)=@_;
my($table)=$self->table;
- dbdef->table($table);
+ $dbdef->table($table);
}
=item get, getfield COLUMN
@@ -677,7 +598,6 @@ otherwise returns false.
sub insert {
my $self = shift;
- my $saved = {};
my $error = $self->check;
return $error if $error;
@@ -708,17 +628,6 @@ sub insert {
}
my $table = $self->table;
-
-
- # Encrypt before the database
- if ($conf->exists('encryption') && defined(eval '@FS::'. $table . 'encrypted_fields')) {
- foreach my $field (eval '@FS::'. $table . '::encrypted_fields') {
- $self->{'saved'} = $self->getfield($field);
- $self->setfield($field, $self->enrypt($self->getfield($field)));
- }
- }
-
-
#false laziness w/delete
my @real_fields =
grep defined($self->getfield($_)) && $self->getfield($_) ne "",
@@ -745,32 +654,18 @@ sub insert {
$sth->execute or return $sth->errstr;
- # get inserted id from the database, if applicable & needed
- if ( $db_seq && ! $self->getfield($primary_key) ) {
+ my $insertid = '';
+ if ( $db_seq ) { # get inserted id from the database, if applicable
warn "[debug]$me retreiving sequence from database\n" if $DEBUG;
-
- my $insertid = '';
-
if ( driver_name eq 'Pg' ) {
- #my $oid = $sth->{'pg_oid_status'};
- #my $i_sql = "SELECT $primary_key FROM $table WHERE oid = ?";
-
- my $default = $self->dbdef_table->column($primary_key)->default;
- unless ( $default =~ /^nextval\('"?([\w\.]+)"?'/i ) {
- dbh->rollback if $FS::UID::AutoCommit;
- return "can't parse $table.$primary_key default value".
- " for sequence name: $default";
- }
- my $sequence = $1;
-
- my $i_sql = "SELECT currval('$sequence')";
+ my $oid = $sth->{'pg_oid_status'};
+ my $i_sql = "SELECT $primary_key FROM $table WHERE oid = ?";
my $i_sth = dbh->prepare($i_sql) or do {
dbh->rollback if $FS::UID::AutoCommit;
return dbh->errstr;
};
- #$i_sth->execute($oid) or do {
- $i_sth->execute() or do {
+ $i_sth->execute($oid) or do {
dbh->rollback if $FS::UID::AutoCommit;
return $i_sth->errstr;
};
@@ -796,15 +691,11 @@ sub insert {
}
} else {
-
dbh->rollback if $FS::UID::AutoCommit;
return "don't know how to retreive inserted ids from ". driver_name.
", try using counterfiles (maybe run dbdef-create?)";
-
}
-
$self->setfield($primary_key, $insertid);
-
}
my @virtual_fields =
@@ -836,7 +727,7 @@ sub insert {
my $h_sth;
- if ( defined dbdef->table('h_'. $table) ) {
+ if ( defined $dbdef->table('h_'. $table) ) {
my $h_statement = $self->_h_statement('insert');
warn "[debug]$me $h_statement\n" if $DEBUG > 2;
$h_sth = dbh->prepare($h_statement) or do {
@@ -850,12 +741,6 @@ sub insert {
dbh->commit or croak dbh->errstr if $FS::UID::AutoCommit;
- # Now that it has been saved, reset the encrypted fields so that $new
- # can still be used.
- foreach my $field (keys %{$saved}) {
- $self->setfield($field, $saved->{$field});
- }
-
'';
}
@@ -897,7 +782,7 @@ sub delete {
my $sth = dbh->prepare($statement) or return dbh->errstr;
my $h_sth;
- if ( defined dbdef->table('h_'. $self->table) ) {
+ if ( defined $dbdef->table('h_'. $self->table) ) {
my $h_statement = $self->_h_statement('delete');
warn "[debug]$me $h_statement\n" if $DEBUG > 2;
$h_sth = dbh->prepare($h_statement) or return dbh->errstr;
@@ -960,9 +845,11 @@ returns the error, otherwise returns false.
sub replace {
my $new = shift;
- my $old = shift;
- if (!defined($old)) {
+ 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;
@@ -980,31 +867,19 @@ sub replace {
return "Records not in same table!" unless $new->table eq $old->table;
my $primary_key = $old->dbdef_table->primary_key;
- return "Can't change primary key $primary_key ".
- 'from '. $old->getfield($primary_key).
- ' to ' . $new->getfield($primary_key)
+ return "Can't change $primary_key"
if $primary_key
&& ( $old->getfield($primary_key) ne $new->getfield($primary_key) );
my $error = $new->check;
return $error if $error;
-
- # Encrypt for replace
- my $saved = {};
- if ($conf->exists('encryption') && defined(eval '@FS::'. $new->table . 'encrypted_fields')) {
- foreach my $field (eval '@FS::'. $new->table . '::encrypted_fields') {
- $saved->{$field} = $new->getfield($field);
- $new->setfield($field, $new->encrypt($new->getfield($field)));
- }
- }
#my @diff = grep $new->getfield($_) ne $old->getfield($_), $old->fields;
my %diff = map { ($new->getfield($_) ne $old->getfield($_))
? ($_, $new->getfield($_)) : () } $old->fields;
unless ( keys(%diff) ) {
- carp "[warning]$me $new -> replace $old: records identical"
- unless $nowarn_identical;
+ carp "[warning]$me $new -> replace $old: records identical";
return '';
}
@@ -1015,25 +890,13 @@ sub replace {
). ' WHERE '.
join(' AND ',
map {
-
- if ( $old->getfield($_) eq '' ) {
-
- #false laziness w/qsearch
- if ( driver_name eq 'Pg' ) {
- my $type = $old->dbdef_table->column($_)->type;
- if ( $type =~ /(int|serial)/i ) {
- qq-( $_ IS NULL )-;
- } else {
- qq-( $_ IS NULL OR $_ = '' )-;
- }
- } else {
- qq-( $_ IS NULL OR $_ = "" )-;
- }
-
- } else {
- "$_ = ". _quote($old->getfield($_),$old->table,$_);
- }
-
+ $old->getfield($_) eq ''
+ #? "( $_ IS NULL OR $_ = \"\" )"
+ ? ( driver_name eq 'Pg'
+ ? "( $_ IS NULL OR $_ = '' )"
+ : "( $_ IS NULL OR $_ = \"\" )"
+ )
+ : "$_ = ". _quote($old->getfield($_),$old->table,$_)
} ( $primary_key ? ( $primary_key ) : real_fields($old->table) )
)
;
@@ -1041,7 +904,7 @@ sub replace {
my $sth = dbh->prepare($statement) or return dbh->errstr;
my $h_old_sth;
- if ( defined dbdef->table('h_'. $old->table) ) {
+ if ( defined $dbdef->table('h_'. $old->table) ) {
my $h_old_statement = $old->_h_statement('replace_old');
warn "[debug]$me $h_old_statement\n" if $DEBUG > 2;
$h_old_sth = dbh->prepare($h_old_statement) or return dbh->errstr;
@@ -1050,7 +913,7 @@ sub replace {
}
my $h_new_sth;
- if ( defined dbdef->table('h_'. $new->table) ) {
+ if ( defined $dbdef->table('h_'. $new->table) ) {
my $h_new_statement = $new->_h_statement('replace_new');
warn "[debug]$me $h_new_statement\n" if $DEBUG > 2;
$h_new_sth = dbh->prepare($h_new_statement) or return dbh->errstr;
@@ -1127,12 +990,6 @@ sub replace {
dbh->commit or croak dbh->errstr if $FS::UID::AutoCommit;
- # Now that it has been saved, reset the encrypted fields so that $new
- # can still be used.
- foreach my $field (keys %{$saved}) {
- $new->setfield($field, $saved->{$field});
- }
-
'';
}
@@ -1182,9 +1039,7 @@ sub check {
}
sub _h_statement {
- my( $self, $action, $time ) = @_;
-
- $time ||= time;
+ my( $self, $action ) = @_;
my @fields =
grep defined($self->getfield($_)) && $self->getfield($_) ne "",
@@ -1195,7 +1050,7 @@ sub _h_statement {
"INSERT INTO h_". $self->table. " ( ".
join(', ', qw(history_date history_user history_action), @fields ).
") VALUES (".
- join(', ', $time, dbh->quote(getotaker()), dbh->quote($action), @values).
+ join(', ', time, dbh->quote(getotaker()), dbh->quote($action), @values).
")"
;
}
@@ -1489,8 +1344,6 @@ Check/untaint zip codes.
=cut
-my @zip_reqd_countries = qw( CA ); #US implicit...
-
sub ut_zip {
my( $self, $field, $country ) = @_;
if ( $country eq 'US' ) {
@@ -1499,10 +1352,7 @@ sub ut_zip {
$self->getfield($field);
$self->setfield($field,$1);
} else {
- if ( $self->getfield($field) =~ /^\s*$/
- && ( !$country || ! grep { $_ eq $country } @zip_reqd_countries )
- )
- {
+ if ( $self->getfield($field) =~ /^\s*$/ ) {
$self->setfield($field,'');
} else {
$self->getfield($field) =~ /^\s*(\w[\w\-\s]{2,8}\w)\s*$/
@@ -1606,9 +1456,9 @@ sub virtual_fields {
my $table;
$table = $self->table or confess "virtual_fields called on non-table";
- confess "Unknown table $table" unless dbdef->table($table);
+ confess "Unknown table $table" unless $dbdef->table($table);
- return () unless dbdef->table('part_virtual_field');
+ return () unless $self->dbdef->table('part_virtual_field');
unless ( $virtual_fields_cache{$table} ) {
my $query = 'SELECT name from part_virtual_field ' .
@@ -1676,11 +1526,40 @@ fields() and other subroutines elsewhere in FS::Record.
sub real_fields {
my $table = shift;
- my($table_obj) = dbdef->table($table);
+ my($table_obj) = $dbdef->table($table);
confess "Unknown table $table" unless $table_obj;
$table_obj->columns;
}
+=item reload_dbdef([FILENAME])
+
+Load a database definition (see L<DBIx::DBSchema>), optionally from a
+non-default filename. This command is executed at startup unless
+I<$FS::Record::setup_hack> is true. Returns a DBIx::DBSchema object.
+
+=cut
+
+sub reload_dbdef {
+ my $file = shift || $dbdef_file;
+
+ unless ( exists $dbdef_cache{$file} ) {
+ warn "[debug]$me loading dbdef for $file\n" if $DEBUG;
+ $dbdef_cache{$file} = DBIx::DBSchema->load( $file )
+ or die "can't load database schema from $file";
+ } else {
+ warn "[debug]$me re-using cached dbdef for $file\n" if $DEBUG;
+ }
+ $dbdef = $dbdef_cache{$file};
+}
+
+=item dbdef
+
+Returns the current database definition. See L<DBIx::DBSchema>.
+
+=cut
+
+sub dbdef { $dbdef; }
+
=item _quote VALUE, TABLE, COLUMN
This is an internal function used to construct SQL statements. It returns
@@ -1691,16 +1570,11 @@ type (see L<DBIx::DBSchema::Column>) does not end in `char' or `binary'.
sub _quote {
my($value, $table, $column) = @_;
- my $column_obj = dbdef->table($table)->column($column);
+ my $column_obj = $dbdef->table($table)->column($column);
my $column_type = $column_obj->type;
- my $nullable = $column_obj->null;
-
- warn " $table.$column: $value ($column_type".
- ( $nullable ? ' NULL' : ' NOT NULL' ).
- ")\n" if $DEBUG > 2;
if ( $value eq '' && $column_type =~ /^int/ ) {
- if ( $nullable ) {
+ if ( $column_obj->null ) {
'NULL';
} else {
cluck "WARNING: Attempting to set non-null integer $table.$column null; ".
@@ -1726,7 +1600,7 @@ sub vfieldpart_hashref {
my $self = shift;
my $table = $self->table;
- return {} unless dbdef->table('part_virtual_field');
+ return {} unless $self->dbdef->table('part_virtual_field');
my $dbh = dbh;
my $statement = "SELECT vfieldpart, name FROM part_virtual_field WHERE ".
@@ -1764,79 +1638,6 @@ sub _dump {
} (fields($self->table)) );
}
-sub encrypt {
- my ($self, $value) = @_;
- my $encrypted;
-
- if ($conf->exists('encryption')) {
- if ($self->is_encrypted($value)) {
- # Return the original value if it isn't plaintext.
- $encrypted = $value;
- } else {
- $self->loadRSA;
- if (ref($rsa_encrypt) =~ /::RSA/) { # We Can Encrypt
- # RSA doesn't like the empty string so let's pack it up
- # The database doesn't like the RSA data so uuencode it
- my $length = length($value)+1;
- $encrypted = pack("u*",$rsa_encrypt->encrypt(pack("Z$length",$value)));
- } else {
- die ("You can't encrypt w/o a valid RSA engine - Check your installation or disable encryption");
- }
- }
- }
- return $encrypted;
-}
-
-sub is_encrypted {
- my ($self, $value) = @_;
- # Possible Bug - Some work may be required here....
-
- if (length($value) > 80) {
- return 1;
- } else {
- return 0;
- }
-}
-
-sub decrypt {
- my ($self,$value) = @_;
- my $decrypted = $value; # Will return the original value if it isn't encrypted or can't be decrypted.
- if ($conf->exists('encryption') && $self->is_encrypted($value)) {
- $self->loadRSA;
- if (ref($rsa_decrypt) =~ /::RSA/) {
- my $encrypted = unpack ("u*", $value);
- $decrypted = unpack("Z*", $rsa_decrypt->decrypt($encrypted));
- }
- }
- return $decrypted;
-}
-
-sub loadRSA {
- my $self = shift;
- #Initialize the Module
- $rsa_module = 'Crypt::OpenSSL::RSA'; # The Default
-
- if ($conf->exists('encryptionmodule') && $conf->config('encryptionmodule') ne '') {
- $rsa_module = $conf->config('encryptionmodule');
- }
-
- if (!$rsa_loaded) {
- eval ("require $rsa_module"); # No need to import the namespace
- $rsa_loaded++;
- }
- # Initialize Encryption
- if ($conf->exists('encryptionpublickey') && $conf->config('encryptionpublickey') ne '') {
- my $public_key = join("\n",$conf->config('encryptionpublickey'));
- $rsa_encrypt = $rsa_module->new_public_key($public_key);
- }
-
- # Intitalize Decryption
- if ($conf->exists('encryptionprivatekey') && $conf->config('encryptionprivatekey') ne '') {
- my $private_key = join("\n",$conf->config('encryptionprivatekey'));
- $rsa_decrypt = $rsa_module->new_private_key($private_key);
- }
-}
-
sub DESTROY { return; }
#sub DESTROY {
diff --git a/FS/FS/Report/Table/Monthly.pm b/FS/FS/Report/Table/Monthly.pm
index 89d44f92f..d3ff5d1db 100644
--- a/FS/FS/Report/Table/Monthly.pm
+++ b/FS/FS/Report/Table/Monthly.pm
@@ -144,44 +144,6 @@ sub credits {
);
}
-sub canceled { #active
- my( $self, $speriod, $eperiod ) = ( shift, shift, shift );
- $self->scalar_sql("
- SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND 0 = ( SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
- )
- AND cust_pkg.cancel > $speriod AND cust_pkg.cancel < $eperiod
- ");
-}
-
-sub newaccount { #newaccount
- my( $self, $speriod, $eperiod ) = ( shift, shift, shift );
- $self->scalar_sql("
- SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
- AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
- AND cust_pkg.setup > $speriod AND cust_pkg.setup < $eperiod
- ");
-}
-
-sub suspended { #suspended
- my( $self, $speriod, $eperiod ) = ( shift, shift, shift );
- $self->scalar_sql("
- SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
- AND 0 = ( SELECT COUNT(*) FROM cust_pkg
- WHERE cust_pkg.custnum = cust_main.custnum
- AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
- )
- AND cust_pkg.susp > $speriod AND cust_pkg.susp < $eperiod
- ");
-}
-
sub in_time_period {
my( $self, $speriod, $eperiod ) = ( shift, shift, shift );
my $table = @_ ? shift().'.' : '';
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
deleted file mode 100644
index 451ef2d2e..000000000
--- a/FS/FS/Schema.pm
+++ /dev/null
@@ -1,1277 +0,0 @@
-package FS::Schema;
-
-use vars qw(@ISA @EXPORT_OK $DEBUG $setup_hack %dbdef_cache);
-use subs qw(reload_dbdef);
-use Exporter;
-use DBIx::DBSchema 0.25;
-use DBIx::DBSchema::Table;
-use DBIx::DBSchema::Column;
-use DBIx::DBSchema::ColGroup::Unique;
-use DBIx::DBSchema::ColGroup::Index;
-use FS::UID qw(datasrc);
-
-@ISA = qw(Exporter);
-@EXPORT_OK = qw( dbdef dbdef_dist reload_dbdef );
-
-$DEBUG = 0;
-$me = '[FS::Schema]';
-
-#ask FS::UID to run this stuff for us later
-FS::UID->install_callback( sub {
- #$conf = new FS::Conf;
- &reload_dbdef("/usr/local/etc/freeside/dbdef.". datasrc)
- unless $setup_hack; #$setup_hack needed now?
-} );
-
-=head1 NAME
-
-FS::Schema - Freeside database schema
-
-=head1 SYNOPSYS
-
- use FS::Schema qw(dbdef dbdef_dist reload_dbdef);
-
- $dbdef = reload_dbdef;
- $dbdef = reload_dbdef "/non/standard/filename";
- $dbdef = dbdef;
- $dbdef_dist = dbdef_dist;
-
-=head1 DESCRIPTION
-
-This class represents the database schema.
-
-=head1 METHODS
-
-=over 4
-
-=item reload_dbdef([FILENAME])
-
-Load a database definition (see L<DBIx::DBSchema>), optionally from a
-non-default filename. This command is executed at startup unless
-I<$FS::Schema::setup_hack> is true. Returns a DBIx::DBSchema object.
-
-=cut
-
-sub reload_dbdef {
- my $file = shift;
-
- unless ( exists $dbdef_cache{$file} ) {
- warn "[debug]$me loading dbdef for $file\n" if $DEBUG;
- $dbdef_cache{$file} = DBIx::DBSchema->load( $file )
- or die "can't load database schema from $file";
- } else {
- warn "[debug]$me re-using cached dbdef for $file\n" if $DEBUG;
- }
- $dbdef = $dbdef_cache{$file};
-}
-
-=item dbdef
-
-Returns the current database definition (represents the current database,
-assuming it is up-to-date). See L<DBIx::DBSchema>.
-
-=cut
-
-sub dbdef { $dbdef; }
-
-=item dbdef_dist [ OPTION => VALUE ... ]
-
-Returns the current canoical database definition as defined in this file.
-
-=cut
-
-sub dbdef_dist {
-
- ###
- # create a dbdef object from the old data structure
- ###
-
- my $tables_hashref = tables_hashref();
-
- #turn it into objects
- my $dbdef = new DBIx::DBSchema map {
- my @columns;
- while (@{$tables_hashref->{$_}{'columns'}}) {
- my($name, $type, $null, $length) =
- splice @{$tables_hashref->{$_}{'columns'}}, 0, 4;
- push @columns, new DBIx::DBSchema::Column ( $name,$type,$null,$length );
- }
- DBIx::DBSchema::Table->new(
- $_,
- $tables_hashref->{$_}{'primary_key'},
- DBIx::DBSchema::ColGroup::Unique->new($tables_hashref->{$_}{'unique'}),
- DBIx::DBSchema::ColGroup::Index->new($tables_hashref->{$_}{'index'}),
- @columns,
- );
- } keys %$tables_hashref;
-
- if ( $DEBUG ) {
- warn "[debug]$me initial dbdef_dist created ($dbdef) with tables:\n";
- warn "[debug]$me $_\n" foreach $dbdef->tables;
- }
-
- my $cust_main = $dbdef->table('cust_main');
- #unless ($ship) { #remove ship_ from cust_main
- # $cust_main->delcolumn($_) foreach ( grep /^ship_/, $cust_main->columns );
- #} else { #add indices
- push @{$cust_main->index->lol_ref},
- map { [ "ship_$_" ] } qw( last company daytime night fax );
- #}
-
- #add radius attributes to svc_acct
- #
- #my($svc_acct)=$dbdef->table('svc_acct');
- #
- #my($attribute);
- #foreach $attribute (@attributes) {
- # $svc_acct->addcolumn ( new DBIx::DBSchema::Column (
- # 'radius_'. $attribute,
- # 'varchar',
- # 'NULL',
- # $char_d,
- # ));
- #}
- #
- #foreach $attribute (@check_attributes) {
- # $svc_acct->addcolumn( new DBIx::DBSchema::Column (
- # 'rc_'. $attribute,
- # 'varchar',
- # 'NULL',
- # $char_d,
- # ));
- #}
-
- #create history tables (false laziness w/create-history-tables)
- foreach my $table (
- grep { ! /^clientapi_session/ }
- grep { ! /^h_/ }
- $dbdef->tables
- ) {
- my $tableobj = $dbdef->table($table)
- or die "unknown table $table";
-
- die "unique->lol_ref undefined for $table"
- unless defined $tableobj->unique->lol_ref;
- die "index->lol_ref undefined for $table"
- unless defined $tableobj->index->lol_ref;
-
- my $h_tableobj = DBIx::DBSchema::Table->new( {
- name => "h_$table",
- primary_key => 'historynum',
- unique => DBIx::DBSchema::ColGroup::Unique->new( [] ),
- 'index' => DBIx::DBSchema::ColGroup::Index->new( [
- @{$tableobj->unique->lol_ref},
- @{$tableobj->index->lol_ref}
- ] ),
- columns => [
- DBIx::DBSchema::Column->new( {
- 'name' => 'historynum',
- 'type' => 'serial',
- 'null' => 'NOT NULL',
- 'length' => '',
- 'default' => '',
- 'local' => '',
- } ),
- DBIx::DBSchema::Column->new( {
- 'name' => 'history_date',
- 'type' => 'int',
- 'null' => 'NULL',
- 'length' => '',
- 'default' => '',
- 'local' => '',
- } ),
- DBIx::DBSchema::Column->new( {
- 'name' => 'history_user',
- 'type' => 'varchar',
- 'null' => 'NOT NULL',
- 'length' => '80',
- 'default' => '',
- 'local' => '',
- } ),
- DBIx::DBSchema::Column->new( {
- 'name' => 'history_action',
- 'type' => 'varchar',
- 'null' => 'NOT NULL',
- 'length' => '80',
- 'default' => '',
- 'local' => '',
- } ),
- map {
- my $column = $tableobj->column($_);
-
- #clone so as to not disturb the original
- $column = DBIx::DBSchema::Column->new( {
- map { $_ => $column->$_() }
- qw( name type null length default local )
- } );
-
- if ( $column->type eq 'serial' ) {
- $column->type('int');
- $column->null('NULL');
- }
- #$column->default('')
- # if $column->default =~ /^nextval\(/i;
- #( my $local = $column->local ) =~ s/AUTO_INCREMENT//i;
- #$column->local($local);
- $column;
- } $tableobj->columns
- ],
- } );
- $dbdef->addtable($h_tableobj);
- }
-
- $dbdef;
-
-}
-
-sub tables_hashref {
-
- my $char_d = 80; #default maxlength for text fields
-
- #my(@date_type) = ( 'timestamp', '', '' );
- my @date_type = ( 'int', 'NULL', '' );
- my @perl_type = ( 'text', 'NULL', '' );
- my @money_type = ( 'decimal', '', '10,2' );
-
- my $username_len = 32; #usernamemax config file
-
- return {
-
- 'agent' => {
- 'columns' => [
- 'agentnum', 'serial', '', '',
- 'agent', 'varchar', '', $char_d,
- 'typenum', 'int', '', '',
- 'freq', 'int', 'NULL', '',
- 'prog', @perl_type,
- 'disabled', 'char', 'NULL', 1,
- 'username', 'varchar', 'NULL', $char_d,
- '_password','varchar', 'NULL', $char_d,
- 'ticketing_queueid', 'int', 'NULL', '',
- ],
- 'primary_key' => 'agentnum',
- 'unique' => [],
- 'index' => [ ['typenum'], ['disabled'] ],
- },
-
- 'agent_type' => {
- 'columns' => [
- 'typenum', 'serial', '', '',
- 'atype', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'typenum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'type_pkgs' => {
- 'columns' => [
- 'typepkgnum', 'serial', '', '',
- 'typenum', 'int', '', '',
- 'pkgpart', 'int', '', '',
- ],
- 'primary_key' => 'typepkgnum',
- 'unique' => [ ['typenum', 'pkgpart'] ],
- 'index' => [ ['typenum'] ],
- },
-
- 'cust_bill' => {
- 'columns' => [
- 'invnum', 'serial', '', '',
- 'custnum', 'int', '', '',
- '_date', @date_type,
- 'charged', @money_type,
- 'printed', 'int', '', '',
- 'closed', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'invnum',
- 'unique' => [],
- 'index' => [ ['custnum'], ['_date'] ],
- },
-
- 'cust_bill_event' => {
- 'columns' => [
- 'eventnum', 'serial', '', '',
- 'invnum', 'int', '', '',
- 'eventpart', 'int', '', '',
- '_date', @date_type,
- 'status', 'varchar', '', $char_d,
- 'statustext', 'text', 'NULL', '',
- ],
- 'primary_key' => 'eventnum',
- #no... there are retries now #'unique' => [ [ 'eventpart', 'invnum' ] ],
- 'unique' => [],
- 'index' => [ ['invnum'], ['status'] ],
- },
-
- 'part_bill_event' => {
- 'columns' => [
- 'eventpart', 'serial', '', '',
- 'payby', 'char', '', 4,
- 'event', 'varchar', '', $char_d,
- 'eventcode', @perl_type,
- 'seconds', 'int', 'NULL', '',
- 'weight', 'int', '', '',
- 'plan', 'varchar', 'NULL', $char_d,
- 'plandata', 'text', 'NULL', '',
- 'disabled', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'eventpart',
- 'unique' => [],
- 'index' => [ ['payby'], ['disabled'], ],
- },
-
- 'cust_bill_pkg' => {
- 'columns' => [
- 'billpkgnum', 'serial', '', '',
- 'pkgnum', 'int', '', '',
- 'invnum', 'int', '', '',
- 'setup', @money_type,
- 'recur', @money_type,
- 'sdate', @date_type,
- 'edate', @date_type,
- 'itemdesc', 'varchar', 'NULL', $char_d,
- ],
- 'primary_key' => 'billpkgnum',
- 'unique' => [],
- 'index' => [ ['invnum'], [ 'pkgnum' ] ],
- },
-
- 'cust_bill_pkg_detail' => {
- 'columns' => [
- 'detailnum', 'serial', '', '',
- 'pkgnum', 'int', '', '',
- 'invnum', 'int', '', '',
- 'detail', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'detailnum',
- 'unique' => [],
- 'index' => [ [ 'pkgnum', 'invnum' ] ],
- },
-
- 'cust_credit' => {
- 'columns' => [
- 'crednum', 'serial', '', '',
- 'custnum', 'int', '', '',
- '_date', @date_type,
- 'amount', @money_type,
- 'otaker', 'varchar', '', 32,
- 'reason', 'text', 'NULL', '',
- 'closed', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'crednum',
- 'unique' => [],
- 'index' => [ ['custnum'] ],
- },
-
- 'cust_credit_bill' => {
- 'columns' => [
- 'creditbillnum', 'serial', '', '',
- 'crednum', 'int', '', '',
- 'invnum', 'int', '', '',
- '_date', @date_type,
- 'amount', @money_type,
- ],
- 'primary_key' => 'creditbillnum',
- 'unique' => [],
- 'index' => [ ['crednum'], ['invnum'] ],
- },
-
- 'cust_main' => {
- 'columns' => [
- 'custnum', 'serial', '', '',
- 'agentnum', 'int', '', '',
-# 'titlenum', 'int', 'NULL', '',
- 'last', 'varchar', '', $char_d,
-# 'middle', 'varchar', 'NULL', $char_d,
- 'first', 'varchar', '', $char_d,
- 'ss', 'varchar', 'NULL', 11,
- 'company', 'varchar', 'NULL', $char_d,
- 'address1', 'varchar', '', $char_d,
- 'address2', 'varchar', 'NULL', $char_d,
- 'city', 'varchar', '', $char_d,
- 'county', 'varchar', 'NULL', $char_d,
- 'state', 'varchar', 'NULL', $char_d,
- 'zip', 'varchar', 'NULL', 10,
- 'country', 'char', '', 2,
- 'daytime', 'varchar', 'NULL', 20,
- 'night', 'varchar', 'NULL', 20,
- 'fax', 'varchar', 'NULL', 12,
- 'ship_last', 'varchar', 'NULL', $char_d,
-# 'ship_middle', 'varchar', 'NULL', $char_d,
- 'ship_first', 'varchar', 'NULL', $char_d,
- 'ship_company', 'varchar', 'NULL', $char_d,
- 'ship_address1', 'varchar', 'NULL', $char_d,
- 'ship_address2', 'varchar', 'NULL', $char_d,
- 'ship_city', 'varchar', 'NULL', $char_d,
- 'ship_county', 'varchar', 'NULL', $char_d,
- 'ship_state', 'varchar', 'NULL', $char_d,
- 'ship_zip', 'varchar', 'NULL', 10,
- 'ship_country', 'char', 'NULL', 2,
- 'ship_daytime', 'varchar', 'NULL', 20,
- 'ship_night', 'varchar', 'NULL', 20,
- 'ship_fax', 'varchar', 'NULL', 12,
- 'payby', 'char', '', 4,
- 'payinfo', 'varchar', 'NULL', 512,
- 'paycvv', 'varchar', 'NULL', 512,
- 'paymask', 'varchar', 'NULL', $char_d,
- #'paydate', @date_type,
- 'paydate', 'varchar', 'NULL', 10,
- 'paystart_month', 'int', 'NULL', '',
- 'paystart_year', 'int', 'NULL', '',
- 'payissue', 'varchar', 'NULL', 2,
- 'payname', 'varchar', 'NULL', $char_d,
- 'payip', 'varchar', 'NULL', 15,
- 'tax', 'char', 'NULL', 1,
- 'otaker', 'varchar', '', 32,
- 'refnum', 'int', '', '',
- 'referral_custnum', 'int', 'NULL', '',
- 'comments', 'text', 'NULL', '',
- ],
- 'primary_key' => 'custnum',
- 'unique' => [],
- #'index' => [ ['last'], ['company'] ],
- 'index' => [ ['last'], [ 'company' ], [ 'referral_custnum' ],
- [ 'daytime' ], [ 'night' ], [ 'fax' ], [ 'refnum' ],
- [ 'county' ], [ 'state' ], [ 'country' ]
- ],
- },
-
- 'cust_main_invoice' => {
- 'columns' => [
- 'destnum', 'serial', '', '',
- 'custnum', 'int', '', '',
- 'dest', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'destnum',
- 'unique' => [],
- 'index' => [ ['custnum'], ],
- },
-
- 'cust_main_county' => { #county+state+country are checked off the
- #cust_main_county for validation and to provide
- # a tax rate.
- 'columns' => [
- 'taxnum', 'serial', '', '',
- 'state', 'varchar', 'NULL', $char_d,
- 'county', 'varchar', 'NULL', $char_d,
- 'country', 'char', '', 2,
- 'taxclass', 'varchar', 'NULL', $char_d,
- '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' => [],
- # 'unique' => [ ['taxnum'], ['state', 'county'] ],
- 'index' => [ [ 'county' ], [ 'state' ], [ 'country' ] ],
- },
-
- 'cust_pay' => {
- 'columns' => [
- 'paynum', 'serial', '', '',
- #now cust_bill_pay #'invnum', 'int', '', '',
- 'custnum', 'int', '', '',
- 'paid', @money_type,
- '_date', @date_type,
- 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index into
- # payment type table.
- 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above
- 'paybatch', 'varchar', 'NULL', $char_d, #for auditing purposes.
- 'closed', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'paynum',
- 'unique' => [],
- 'index' => [ [ 'custnum' ], [ 'paybatch' ], [ 'payby' ], [ '_date' ] ],
- },
-
- 'cust_pay_void' => {
- 'columns' => [
- 'paynum', 'int', '', '',
- 'custnum', 'int', '', '',
- 'paid', @money_type,
- '_date', @date_type,
- 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index into
- # payment type table.
- 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above
- 'paybatch', 'varchar', 'NULL', $char_d, #for auditing purposes.
- 'closed', 'char', 'NULL', 1,
- 'void_date', @date_type,
- 'reason', 'varchar', 'NULL', $char_d,
- 'otaker', 'varchar', '', 32,
- ],
- 'primary_key' => 'paynum',
- 'unique' => [],
- 'index' => [ [ 'custnum' ] ],
- },
-
- 'cust_bill_pay' => {
- 'columns' => [
- 'billpaynum', 'serial', '', '',
- 'invnum', 'int', '', '',
- 'paynum', 'int', '', '',
- 'amount', @money_type,
- '_date', @date_type
- ],
- 'primary_key' => 'billpaynum',
- 'unique' => [],
- 'index' => [ [ 'paynum' ], [ 'invnum' ] ],
- },
-
- 'cust_pay_batch' => { #what's this used for again? list of customers
- #in current CARD batch? (necessarily CARD?)
- 'columns' => [
- 'paybatchnum', 'serial', '', '',
- 'invnum', 'int', '', '',
- 'custnum', 'int', '', '',
- 'last', 'varchar', '', $char_d,
- 'first', 'varchar', '', $char_d,
- 'address1', 'varchar', '', $char_d,
- 'address2', 'varchar', 'NULL', $char_d,
- 'city', 'varchar', '', $char_d,
- 'state', 'varchar', 'NULL', $char_d,
- 'zip', 'varchar', 'NULL', 10,
- 'country', 'char', '', 2,
-# 'trancode', 'int', '', '',
- 'cardnum', 'varchar', '', 16,
- #'exp', @date_type,
- 'exp', 'varchar', '', 11,
- 'payname', 'varchar', 'NULL', $char_d,
- 'amount', @money_type,
- ],
- 'primary_key' => 'paybatchnum',
- 'unique' => [],
- 'index' => [ ['invnum'], ['custnum'] ],
- },
-
- 'cust_pkg' => {
- 'columns' => [
- 'pkgnum', 'serial', '', '',
- 'custnum', 'int', '', '',
- 'pkgpart', 'int', '', '',
- 'otaker', 'varchar', '', 32,
- 'setup', @date_type,
- 'bill', @date_type,
- 'last_bill', @date_type,
- 'susp', @date_type,
- 'cancel', @date_type,
- 'expire', @date_type,
- 'manual_flag', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'pkgnum',
- 'unique' => [],
- 'index' => [ ['custnum'], ['pkgpart'] ],
- },
-
- 'cust_refund' => {
- 'columns' => [
- 'refundnum', 'serial', '', '',
- #now cust_credit_refund #'crednum', 'int', '', '',
- 'custnum', 'int', '', '',
- '_date', @date_type,
- 'refund', @money_type,
- 'otaker', 'varchar', '', 32,
- 'reason', 'varchar', '', $char_d,
- 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index
- # into payment type table.
- 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above
- 'paybatch', 'varchar', 'NULL', $char_d,
- 'closed', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'refundnum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'cust_credit_refund' => {
- 'columns' => [
- 'creditrefundnum', 'serial', '', '',
- 'crednum', 'int', '', '',
- 'refundnum', 'int', '', '',
- 'amount', @money_type,
- '_date', @date_type
- ],
- 'primary_key' => 'creditrefundnum',
- 'unique' => [],
- 'index' => [ [ 'crednum', 'refundnum' ] ],
- },
-
-
- 'cust_svc' => {
- 'columns' => [
- 'svcnum', 'serial', '', '',
- 'pkgnum', 'int', 'NULL', '',
- 'svcpart', 'int', '', '',
- ],
- 'primary_key' => 'svcnum',
- 'unique' => [],
- 'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ],
- },
-
- 'part_pkg' => {
- 'columns' => [
- 'pkgpart', 'serial', '', '',
- 'pkg', 'varchar', '', $char_d,
- 'comment', 'varchar', '', $char_d,
- 'promo_code', 'varchar', 'NULL', $char_d,
- 'setup', @perl_type,
- 'freq', 'varchar', '', $char_d, #billing frequency
- 'recur', @perl_type,
- 'setuptax', 'char', 'NULL', 1,
- 'recurtax', 'char', 'NULL', 1,
- 'plan', 'varchar', 'NULL', $char_d,
- 'plandata', 'text', 'NULL', '',
- 'disabled', 'char', 'NULL', 1,
- 'taxclass', 'varchar', 'NULL', $char_d,
- ],
- 'primary_key' => 'pkgpart',
- 'unique' => [],
- 'index' => [ [ 'promo_code' ], [ 'disabled' ] ],
- },
-
-# 'part_title' => {
-# 'columns' => [
-# 'titlenum', 'int', '', '',
-# 'title', 'varchar', '', $char_d,
-# ],
-# 'primary_key' => 'titlenum',
-# 'unique' => [ [] ],
-# 'index' => [ [] ],
-# },
-
- 'pkg_svc' => {
- 'columns' => [
- 'pkgsvcnum', 'serial', '', '',
- 'pkgpart', 'int', '', '',
- 'svcpart', 'int', '', '',
- 'quantity', 'int', '', '',
- 'primary_svc','char', 'NULL', 1,
- ],
- 'primary_key' => 'pkgsvcnum',
- 'unique' => [ ['pkgpart', 'svcpart'] ],
- 'index' => [ ['pkgpart'] ],
- },
-
- 'part_referral' => {
- 'columns' => [
- 'refnum', 'serial', '', '',
- 'referral', 'varchar', '', $char_d,
- 'disabled', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'refnum',
- 'unique' => [],
- 'index' => [ ['disabled'] ],
- },
-
- 'part_svc' => {
- 'columns' => [
- 'svcpart', 'serial', '', '',
- 'svc', 'varchar', '', $char_d,
- 'svcdb', 'varchar', '', $char_d,
- 'disabled', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'svcpart',
- 'unique' => [],
- 'index' => [ [ 'disabled' ] ],
- },
-
- 'part_svc_column' => {
- 'columns' => [
- 'columnnum', 'serial', '', '',
- 'svcpart', 'int', '', '',
- 'columnname', 'varchar', '', 64,
- 'columnvalue', 'varchar', 'NULL', $char_d,
- 'columnflag', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'columnnum',
- 'unique' => [ [ 'svcpart', 'columnname' ] ],
- 'index' => [ [ 'svcpart' ] ],
- },
-
- #(this should be renamed to part_pop)
- 'svc_acct_pop' => {
- 'columns' => [
- 'popnum', 'serial', '', '',
- 'city', 'varchar', '', $char_d,
- 'state', 'varchar', '', $char_d,
- 'ac', 'char', '', 3,
- 'exch', 'char', '', 3,
- 'loc', 'char', 'NULL', 4, #NULL for legacy purposes
- ],
- 'primary_key' => 'popnum',
- 'unique' => [],
- 'index' => [ [ 'state' ] ],
- },
-
- 'part_pop_local' => {
- 'columns' => [
- 'localnum', 'serial', '', '',
- 'popnum', 'int', '', '',
- 'city', 'varchar', 'NULL', $char_d,
- 'state', 'char', 'NULL', 2,
- 'npa', 'char', '', 3,
- 'nxx', 'char', '', 3,
- ],
- 'primary_key' => 'localnum',
- 'unique' => [],
- 'index' => [ [ 'npa', 'nxx' ], [ 'popnum' ] ],
- },
-
- 'svc_acct' => {
- 'columns' => [
- 'svcnum', 'int', '', '',
- 'username', 'varchar', '', $username_len, #unique (& remove dup code)
- '_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', '',
- 'gid', 'int', 'NULL', '',
- 'finger', 'varchar', 'NULL', $char_d,
- 'dir', 'varchar', 'NULL', $char_d,
- 'shell', 'varchar', 'NULL', $char_d,
- 'quota', 'varchar', 'NULL', $char_d,
- 'slipip', 'varchar', 'NULL', 15, #four TINYINTs, bah.
- 'seconds', 'int', 'NULL', '', #uhhhh
- 'domsvc', 'int', '', '',
- ],
- 'primary_key' => 'svcnum',
- #'unique' => [ [ 'username', 'domsvc' ] ],
- 'unique' => [],
- 'index' => [ ['username'], ['domsvc'] ],
- },
-
- #'svc_charge' => {
- # 'columns' => [
- # 'svcnum', 'int', '', '',
- # 'amount', @money_type,
- # ],
- # 'primary_key' => 'svcnum',
- # 'unique' => [ [] ],
- # 'index' => [ [] ],
- #},
-
- 'svc_domain' => {
- 'columns' => [
- 'svcnum', 'int', '', '',
- 'domain', 'varchar', '', $char_d,
- 'catchall', 'int', 'NULL', '',
- ],
- 'primary_key' => 'svcnum',
- 'unique' => [ ['domain'] ],
- 'index' => [],
- },
-
- 'domain_record' => {
- 'columns' => [
- 'recnum', 'serial', '', '',
- 'svcnum', 'int', '', '',
- #'reczone', 'varchar', '', $char_d,
- 'reczone', 'varchar', '', 255,
- 'recaf', 'char', '', 2,
- 'rectype', 'varchar', '', 5,
- #'recdata', 'varchar', '', $char_d,
- 'recdata', 'varchar', '', 255,
- ],
- 'primary_key' => 'recnum',
- 'unique' => [],
- 'index' => [ ['svcnum'] ],
- },
-
- 'svc_forward' => {
- 'columns' => [
- 'svcnum', 'int', '', '',
- 'srcsvc', 'int', 'NULL', '',
- 'src', 'varchar', 'NULL', 255,
- 'dstsvc', 'int', 'NULL', '',
- 'dst', 'varchar', 'NULL', 255,
- ],
- 'primary_key' => 'svcnum',
- 'unique' => [],
- 'index' => [ ['srcsvc'], ['dstsvc'] ],
- },
-
- 'svc_www' => {
- 'columns' => [
- 'svcnum', 'int', '', '',
- 'recnum', 'int', '', '',
- 'usersvc', 'int', '', '',
- ],
- 'primary_key' => 'svcnum',
- 'unique' => [],
- 'index' => [],
- },
-
- #'svc_wo' => {
- # 'columns' => [
- # 'svcnum', 'int', '', '',
- # 'svcnum', 'int', '', '',
- # 'svcnum', 'int', '', '',
- # 'worker', 'varchar', '', $char_d,
- # '_date', @date_type,
- # ],
- # 'primary_key' => 'svcnum',
- # 'unique' => [ [] ],
- # 'index' => [ [] ],
- #},
-
- 'prepay_credit' => {
- 'columns' => [
- 'prepaynum', 'serial', '', '',
- 'identifier', 'varchar', '', $char_d,
- 'amount', @money_type,
- 'seconds', 'int', 'NULL', '',
- 'agentnum', 'int', 'NULL', '',
- ],
- 'primary_key' => 'prepaynum',
- 'unique' => [ ['identifier'] ],
- 'index' => [],
- },
-
- 'port' => {
- 'columns' => [
- 'portnum', 'serial', '', '',
- 'ip', 'varchar', 'NULL', 15,
- 'nasport', 'int', 'NULL', '',
- 'nasnum', 'int', '', '',
- ],
- 'primary_key' => 'portnum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'nas' => {
- 'columns' => [
- 'nasnum', 'serial', '', '',
- 'nas', 'varchar', '', $char_d,
- 'nasip', 'varchar', '', 15,
- 'nasfqdn', 'varchar', '', $char_d,
- 'last', 'int', '', '',
- ],
- 'primary_key' => 'nasnum',
- 'unique' => [ [ 'nas' ], [ 'nasip' ] ],
- 'index' => [ [ 'last' ] ],
- },
-
- 'session' => {
- 'columns' => [
- 'sessionnum', 'serial', '', '',
- 'portnum', 'int', '', '',
- 'svcnum', 'int', '', '',
- 'login', @date_type,
- 'logout', @date_type,
- ],
- 'primary_key' => 'sessionnum',
- 'unique' => [],
- 'index' => [ [ 'portnum' ] ],
- },
-
- 'queue' => {
- 'columns' => [
- 'jobnum', 'serial', '', '',
- 'job', 'text', '', '',
- '_date', 'int', '', '',
- 'status', 'varchar', '', $char_d,
- 'statustext', 'text', 'NULL', '',
- 'svcnum', 'int', 'NULL', '',
- ],
- 'primary_key' => 'jobnum',
- 'unique' => [],
- 'index' => [ [ 'svcnum' ], [ 'status' ] ],
- },
-
- 'queue_arg' => {
- 'columns' => [
- 'argnum', 'serial', '', '',
- 'jobnum', 'int', '', '',
- 'arg', 'text', 'NULL', '',
- ],
- 'primary_key' => 'argnum',
- 'unique' => [],
- 'index' => [ [ 'jobnum' ] ],
- },
-
- 'queue_depend' => {
- 'columns' => [
- 'dependnum', 'serial', '', '',
- 'jobnum', 'int', '', '',
- 'depend_jobnum', 'int', '', '',
- ],
- 'primary_key' => 'dependnum',
- 'unique' => [],
- 'index' => [ [ 'jobnum' ], [ 'depend_jobnum' ] ],
- },
-
- 'export_svc' => {
- 'columns' => [
- 'exportsvcnum' => 'serial', '', '',
- 'exportnum' => 'int', '', '',
- 'svcpart' => 'int', '', '',
- ],
- 'primary_key' => 'exportsvcnum',
- 'unique' => [ [ 'exportnum', 'svcpart' ] ],
- 'index' => [ [ 'exportnum' ], [ 'svcpart' ] ],
- },
-
- 'part_export' => {
- 'columns' => [
- 'exportnum', 'serial', '', '',
- #'svcpart', 'int', '', '',
- 'machine', 'varchar', '', $char_d,
- 'exporttype', 'varchar', '', $char_d,
- 'nodomain', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'exportnum',
- 'unique' => [],
- 'index' => [ [ 'machine' ], [ 'exporttype' ] ],
- },
-
- 'part_export_option' => {
- 'columns' => [
- 'optionnum', 'serial', '', '',
- 'exportnum', 'int', '', '',
- 'optionname', 'varchar', '', $char_d,
- 'optionvalue', 'text', 'NULL', '',
- ],
- 'primary_key' => 'optionnum',
- 'unique' => [],
- 'index' => [ [ 'exportnum' ], [ 'optionname' ] ],
- },
-
- 'radius_usergroup' => {
- 'columns' => [
- 'usergroupnum', 'serial', '', '',
- 'svcnum', 'int', '', '',
- 'groupname', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'usergroupnum',
- 'unique' => [],
- 'index' => [ [ 'svcnum' ], [ 'groupname' ] ],
- },
-
- 'msgcat' => {
- 'columns' => [
- 'msgnum', 'serial', '', '',
- 'msgcode', 'varchar', '', $char_d,
- 'locale', 'varchar', '', 16,
- 'msg', 'text', '', '',
- ],
- 'primary_key' => 'msgnum',
- 'unique' => [ [ 'msgcode', 'locale' ] ],
- 'index' => [],
- },
-
- 'cust_tax_exempt' => {
- 'columns' => [
- 'exemptnum', 'serial', '', '',
- 'custnum', 'int', '', '',
- 'taxnum', 'int', '', '',
- 'year', 'int', '', '',
- 'month', 'int', '', '',
- 'amount', @money_type,
- ],
- 'primary_key' => 'exemptnum',
- 'unique' => [ [ 'custnum', 'taxnum', 'year', 'month' ] ],
- 'index' => [],
- },
-
- 'router' => {
- 'columns' => [
- 'routernum', 'serial', '', '',
- 'routername', 'varchar', '', $char_d,
- 'svcnum', 'int', 'NULL', '',
- ],
- 'primary_key' => 'routernum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'part_svc_router' => {
- 'columns' => [
- 'svcrouternum', 'serial', '', '',
- 'svcpart', 'int', '', '',
- 'routernum', 'int', '', '',
- ],
- 'primary_key' => 'svcrouternum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'addr_block' => {
- 'columns' => [
- 'blocknum', 'serial', '', '',
- 'routernum', 'int', '', '',
- 'ip_gateway', 'varchar', '', 15,
- 'ip_netmask', 'int', '', '',
- ],
- 'primary_key' => 'blocknum',
- 'unique' => [ [ 'blocknum', 'routernum' ] ],
- 'index' => [],
- },
-
- 'svc_broadband' => {
- 'columns' => [
- 'svcnum', 'int', '', '',
- 'blocknum', 'int', '', '',
- 'speed_up', 'int', '', '',
- 'speed_down', 'int', '', '',
- 'ip_addr', 'varchar', '', 15,
- ],
- 'primary_key' => 'svcnum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'part_virtual_field' => {
- 'columns' => [
- 'vfieldpart', 'int', '', '',
- 'dbtable', 'varchar', '', 32,
- 'name', 'varchar', '', 32,
- 'check_block', 'text', 'NULL', '',
- 'length', 'int', 'NULL', '',
- 'list_source', 'text', 'NULL', '',
- 'label', 'varchar', 'NULL', 80,
- ],
- 'primary_key' => 'vfieldpart',
- 'unique' => [],
- 'index' => [],
- },
-
- 'virtual_field' => {
- 'columns' => [
- 'vfieldnum', 'serial', '', '',
- 'recnum', 'int', '', '',
- 'vfieldpart', 'int', '', '',
- 'value', 'varchar', '', 128,
- ],
- 'primary_key' => 'vfieldnum',
- 'unique' => [ [ 'vfieldpart', 'recnum' ] ],
- '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', 'NULL', '',
- 'title', 'varchar', 'NULL', $char_d,
- ],
- 'primary_key' => 'svcnum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'cust_pay_refund' => {
- 'columns' => [
- 'payrefundnum', 'serial', '', '',
- 'paynum', 'int', '', '',
- 'refundnum', 'int', '', '',
- '_date', @date_type,
- 'amount', @money_type,
- ],
- 'primary_key' => 'payrefundnum',
- 'unique' => [],
- 'index' => [ ['paynum'], ['refundnum'] ],
- },
-
- 'part_pkg_option' => {
- 'columns' => [
- 'optionnum', 'serial', '', '',
- 'pkgpart', 'int', '', '',
- 'optionname', 'varchar', '', $char_d,
- 'optionvalue', 'text', 'NULL', '',
- ],
- 'primary_key' => 'optionnum',
- 'unique' => [],
- 'index' => [ [ 'pkgpart' ], [ 'optionname' ] ],
- },
-
- 'rate' => {
- 'columns' => [
- 'ratenum', 'serial', '', '',
- 'ratename', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'ratenum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'rate_detail' => {
- 'columns' => [
- 'ratedetailnum', 'serial', '', '',
- 'ratenum', 'int', '', '',
- 'orig_regionnum', 'int', 'NULL', '',
- 'dest_regionnum', 'int', '', '',
- 'min_included', 'int', '', '',
- 'min_charge', @money_type,
- 'sec_granularity', 'int', '', '',
- #time period (link to table of periods)?
- ],
- 'primary_key' => 'ratedetailnum',
- 'unique' => [ [ 'ratenum', 'orig_regionnum', 'dest_regionnum' ] ],
- 'index' => [ [ 'ratenum', 'dest_regionnum' ] ],
- },
-
- 'rate_region' => {
- 'columns' => [
- 'regionnum', 'serial', '', '',
- 'regionname', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'regionnum',
- 'unique' => [],
- 'index' => [],
- },
-
- 'rate_prefix' => {
- 'columns' => [
- 'prefixnum', 'serial', '', '',
- 'regionnum', 'int', '', '',,
- 'countrycode', 'varchar', '', 3,
- 'npa', 'varchar', 'NULL', 6,
- 'nxx', 'varchar', 'NULL', 3,
- ],
- 'primary_key' => 'prefixnum',
- 'unique' => [],
- 'index' => [ [ 'countrycode' ], [ 'regionnum' ] ],
- },
-
- 'reg_code' => {
- 'columns' => [
- 'codenum', 'serial', '', '',
- 'code', 'varchar', '', $char_d,
- 'agentnum', 'int', '', '',
- ],
- 'primary_key' => 'codenum',
- 'unique' => [ [ 'agentnum', 'code' ] ],
- 'index' => [ [ 'agentnum' ] ],
- },
-
- 'reg_code_pkg' => {
- 'columns' => [
- 'codepkgnum', 'serial', '', '',
- 'codenum', 'int', '', '',
- 'pkgpart', 'int', '', '',
- ],
- 'primary_key' => 'codepkgnum',
- 'unique' => [ [ 'codenum', 'pkgpart' ] ],
- 'index' => [ [ 'codenum' ] ],
- },
-
- 'clientapi_session' => {
- 'columns' => [
- 'sessionnum', 'serial', '', '',
- 'sessionid', 'varchar', '', $char_d,
- 'namespace', 'varchar', '', $char_d,
- ],
- 'primary_key' => 'sessionnum',
- 'unique' => [ [ 'sessionid', 'namespace' ] ],
- 'index' => [],
- },
-
- 'clientapi_session_field' => {
- 'columns' => [
- 'fieldnum', 'serial', '', '',
- 'sessionnum', 'int', '', '',
- 'fieldname', 'varchar', '', $char_d,
- 'fieldvalue', 'text', 'NULL', '',
- ],
- 'primary_key' => 'fieldnum',
- 'unique' => [ [ 'sessionnum', 'fieldname' ] ],
- 'index' => [],
- },
-
- 'payment_gateway' => {
- 'columns' => [
- 'gatewaynum', 'serial', '', '',
- 'gateway_module', 'varchar', '', $char_d,
- 'gateway_username', 'varchar', 'NULL', $char_d,
- 'gateway_password', 'varchar', 'NULL', $char_d,
- 'gateway_action', 'varchar', 'NULL', $char_d,
- 'disabled', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'gatewaynum',
- 'unique' => [],
- 'index' => [ [ 'disabled' ] ],
- },
-
- 'payment_gateway_option' => {
- 'columns' => [
- 'optionnum', 'serial', '', '',
- 'gatewaynum', 'int', '', '',
- 'optionname', 'varchar', '', $char_d,
- 'optionvalue', 'text', 'NULL', '',
- ],
- 'primary_key' => 'optionnum',
- 'unique' => [],
- 'index' => [ [ 'gatewaynum' ], [ 'optionname' ] ],
- },
-
- 'agent_payment_gateway' => {
- 'columns' => [
- 'agentgatewaynum', 'serial', '', '',
- 'agentnum', 'int', '', '',
- 'gatewaynum', 'int', '', '',
- 'cardtype', 'varchar', 'NULL', $char_d,
- 'taxclass', 'varchar', 'NULL', $char_d,
- ],
- 'primary_key' => 'agentgatewaynum',
- 'unique' => [],
- 'index' => [ [ 'agentnum', 'cardtype' ], ],
- },
-
- 'banned_pay' => {
- 'columns' => [
- 'bannum', 'serial', '', '',
- 'payby', 'char', '', 4,
- 'payinfo', 'varchar', '', 128, #say, a 512-big digest _hex encoded
- #'paymask', 'varchar', 'NULL', $char_d,
- '_date', @date_type,
- 'otaker', 'varchar', '', 32,
- 'reason', 'varchar', 'NULL', $char_d,
- ],
- 'primary_key' => 'bannum',
- 'unique' => [ [ 'payby', 'payinfo' ] ],
- 'index' => [],
- },
-
- 'cancel_reason' => {
- 'columns' => [
- 'reasonnum', 'serial', '', '',
- 'reason', 'varchar', '', $char_d,
- 'disabled', 'char', 'NULL', 1,
- ],
- 'primary_key' => 'reasonnum',
- 'unique' => [],
- 'index' => [ [ 'disabled' ] ],
- },
-
- };
-
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<DBIx::DBSchema>
-
-=cut
-
-1;
-
diff --git a/FS/FS/TicketSystem.pm b/FS/FS/TicketSystem.pm
index a80a82789..9d961fc47 100644
--- a/FS/FS/TicketSystem.pm
+++ b/FS/FS/TicketSystem.pm
@@ -5,10 +5,10 @@ use vars qw( $conf $system $AUTOLOAD );
use FS::Conf;
use FS::UID;
-FS::UID->install_callback( sub {
+install_callback FS::UID sub {
$conf = new FS::Conf;
$system = $conf->config('ticket_system');
-} );
+};
sub AUTOLOAD {
my $self = shift;
diff --git a/FS/FS/TicketSystem/RT_External.pm b/FS/FS/TicketSystem/RT_External.pm
index d951cc0e7..be0823860 100644
--- a/FS/FS/TicketSystem/RT_External.pm
+++ b/FS/FS/TicketSystem/RT_External.pm
@@ -2,14 +2,11 @@ package FS::TicketSystem::RT_External;
use strict;
use vars qw( $conf $default_queueid
- $priority_field $priority_field_queue $field
- $dbh $external_url );
+ $priority_field $priority_field_queue $field );
use URI::Escape;
-use FS::UID qw(dbh);
-use FS::Record qw(qsearchs);
-use FS::cust_main;
+use FS::UID;
-FS::UID->install_callback( sub {
+install_callback FS::UID sub {
my $conf = new FS::Conf;
$default_queueid = $conf->config('ticket_system-default_queueid');
$priority_field =
@@ -24,25 +21,16 @@ FS::UID->install_callback( sub {
$priority_field_queue = '';
$field = '';
}
-
- $external_url = '';
- $dbh = dbh;
- if ($conf->config('ticket_system') eq 'RT_External') {
- my ($datasrc, $user, $pass) = $conf->config('ticket_system-rt_external_datasrc');
- $dbh = DBI->connect($datasrc, $user, $pass, { 'ChopBlanks' => 1 })
- or die "RT_External DBI->connect error: $DBI::errstr\n";
-
- $external_url = $conf->config('ticket_system-rt_external_url');
- }
-
-} );
+};
sub num_customer_tickets {
- my( $self, $custnum, $priority ) = @_;
+ my( $self, $custnum, $priority, $dbh ) = @_;
+
+ #$dbh ||= create one from some config options
my( $from_sql, @param) = $self->_from_customer( $custnum, $priority );
- my $sql = "SELECT COUNT(*) $from_sql";
+ my $sql = "select count(*) $from_sql";
my $sth = $dbh->prepare($sql) or die $dbh->errstr. " preparing $sql";
$sth->execute(@param) or die $sth->errstr. " executing $sql";
@@ -51,13 +39,15 @@ sub num_customer_tickets {
}
sub customer_tickets {
- my( $self, $custnum, $limit, $priority ) = @_;
+ my( $self, $custnum, $limit, $priority, $dbh ) = @_;
$limit ||= 0;
+ #$dbh ||= create one from some config options
+
my( $from_sql, @param) = $self->_from_customer( $custnum, $priority );
- my $sql = "SELECT tickets.*, queues.name".
- ( length($priority) ? ", objectcustomfieldvalues.content" : '' ).
- " $from_sql ORDER BY priority DESC LIMIT $limit";
+ my $sql = "select tickets.*, queues.name".
+ ( length($priority) ? ", ticketcustomfieldvalues.content" : '' ).
+ " $from_sql order by priority desc limit $limit";
my $sth = $dbh->prepare($sql) or die $dbh->errstr. "preparing $sql";
$sth->execute(@param) or die $sth->errstr. "executing $sql";
@@ -75,23 +65,9 @@ sub _from_customer {
my $where = '';
if ( defined($priority) ) {
- my $queue_sql = " ObjectCustomFields.ObjectId = ( SELECT id FROM queues
- WHERE queues.name = ? )
- OR ( ? = '' AND ObjectCustomFields.ObjectId = 0 )";
-
- my $customfield_sql =
- "customfield = (
- SELECT CustomFields.Id FROM CustomFields
- JOIN ObjectCustomFields
- ON ( CustomFields.id = ObjectCustomFields.CustomField )
- WHERE LookupType = 'RT::Queue-RT::Ticket'
- AND name = ?
- AND ( $queue_sql )
- )";
-
- push @param, $priority_field,
- $priority_field_queue,
- $priority_field_queue;
+ my $queue_sql = " customfields.queue = ( select id from queues
+ where queues.name = ? )
+ or ( ? = '' and customfields.queue = 0 )";
if ( length($priority) ) {
#$where = "
@@ -103,35 +79,40 @@ sub _from_customer {
# )
# )
#";
- unshift @param, $priority;
+ push @param, $priority;
- $join = "JOIN ObjectCustomFieldValues
- ON ( tickets.id = ObjectCustomFieldValues.ObjectId )";
+ $join = "join TicketCustomFieldValues
+ on ( tickets.id = TicketCustomFieldValues.ticket )";
- $where = " AND content = ?
- AND ObjectType = 'RT::Ticket'
- AND $customfield_sql";
-
+ $where = "and content = ?
+ and customfield = ( select id from customfields
+ where name = ?
+ and ( $queue_sql )
+ )
+ ";
} else {
-
$where =
- "AND 0 = ( SELECT count(*) FROM ObjectCustomFieldValues
- WHERE ObjectId = tickets.id
- AND ObjectType = 'RT::Ticket'
- AND $customfield_sql
+ "and 0 = ( select count(*) from TicketCustomFieldValues
+ where ticket = tickets.id
+ and customfield = ( select id from customfields
+ where name = ?
+ and ( $queue_sql )
+ )
)
";
}
-
+ push @param, $priority_field,
+ $priority_field_queue,
+ $priority_field_queue;
}
my $sql = "
- FROM tickets
- JOIN queues ON ( tickets.queue = queues.id )
- JOIN links ON ( tickets.id = links.localbase )
+ from tickets
+ join queues on ( tickets.queue = queues.id )
+ join links on ( tickets.id = links.localbase )
$join
- WHERE ( status = 'new' OR status = 'open' OR status = 'stalled' )
- AND target = 'freeside://freeside/cust_main/$custnum'
+ where ( status = 'new' or status = 'open' or status = 'stalled' )
+ and target = 'freeside://freeside/cust_main/$custnum'
$where
";
@@ -142,11 +123,9 @@ sub _from_customer {
sub href_customer_tickets {
my( $self, $custnum, $priority ) = @_;
- my $href = $self->baseurl;
-
#i snarfed this from an RT bookmarked search, it could be unescaped in the
#source for readability and run through uri_escape
- $href .=
+ my $href =
'Search/Results.html?Order=ASC&Query=%20MemberOf%20%3D%20%27freeside%3A%2F%2Ffreeside%2Fcust_main%2F'.
$custnum.
'%27%20%20AND%20%28%20Status%20%3D%20%27open%27%20%20OR%20Status%20%3D%20%27new%27%20%20OR%20Status%20%3D%20%27stalled%27%20%29%20'
@@ -166,11 +145,7 @@ sub href_customer_tickets {
$href .= '&Rows=100'.
'&OrderBy=id&Page=1'.
- '&Format=%27%20%20%20%3Cb%3E%3Ca%20href%3D%22'.
- $self->baseurl.
- 'Ticket%2FDisplay.html%3Fid%3D__id__%22%3E__id__%3C%2Fa%3E%3C%2Fb%3E%2FTITLE%3A%23%27%2C%20%0A%27%3Cb%3E%3Ca%20href%3D%22'.
- $self->baseurl.
- 'Ticket%2FDisplay.html%3Fid%3D__id__%22%3E__Subject__%3C%2Fa%3E%3C%2Fb%3E%2FTITLE%3ASubject%27%2C%20%0A%27__Status__%27%2C%20';
+ '&Format=%27%20%20%20%3Cb%3E%3Ca%20href%3D%22%2Ffreeside%2Frt%2FTicket%2FDisplay.html%3Fid%3D__id__%22%3E__id__%3C%2Fa%3E%3C%2Fb%3E%2FTITLE%3A%23%27%2C%20%0A%27%3Cb%3E%3Ca%20href%3D%22%2Ffreeside%2Frt%2FTicket%2FDisplay.html%3Fid%3D__id__%22%3E__Subject__%3C%2Fa%3E%3C%2Fb%3E%2FTITLE%3ASubject%27%2C%20%0A%27__Status__%27%2C%20';
if ( defined($priority) && $field ) {
$href .= '%0A%27__CustomField.'. $field. '__%2FTITLE%3ASeverity%27%2C%20';
@@ -185,25 +160,13 @@ sub href_customer_tickets {
$href .= '%20%0A%27%3Csmall%3E__ToldRelative__%3C%2Fsmall%3E%27%2C%20%0A%27%3Csmall%3E__LastUpdatedRelative__%3C%2Fsmall%3E%27%2C%20%0A%27%3Csmall%3E__TimeLeft__%3C%2Fsmall%3E%27';
$href;
-
}
-sub href_new_ticket {
- my( $self, $custnum_or_cust_main, $requestors ) = @_;
-
- my( $custnum, $cust_main );
- if ( ref($custnum_or_cust_main) ) {
- $cust_main = $custnum_or_cust_main;
- $custnum = $cust_main->custnum;
- } else {
- $custnum = $custnum_or_cust_main;
- $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } );
- }
- my $queueid = $cust_main->agent->ticketing_queueid || $default_queueid;
- $self->baseurl.
+sub href_new_ticket {
+ my( $self, $custnum, $requestors ) = @_;
'Ticket/Create.html?'.
- "Queue=$queueid".
+ "Queue=$default_queueid".
"&new-MemberOf=freeside://freeside/cust_main/$custnum".
( $requestors ? '&Requestors='. uri_escape($requestors) : '' )
;
@@ -211,36 +174,7 @@ sub href_new_ticket {
sub href_ticket {
my($self, $ticketnum) = @_;
- $self->baseurl. 'Ticket/Display.html?id='.$ticketnum;
-}
-
-sub queues {
- my($self) = @_;
-
- my $sql = "SELECT id, name FROM queues WHERE disabled = 0";
- my $sth = $dbh->prepare($sql) or die $dbh->errstr. " preparing $sql";
- $sth->execute() or die $sth->errstr. " executing $sql";
-
- map { $_->[0] => $_->[1] } @{ $sth->fetchall_arrayref([]) };
-
-}
-
-sub queue {
- my($self, $queueid) = @_;
-
- return '' unless $queueid;
-
- my $sql = "SELECT name FROM queues WHERE id = ?";
- my $sth = $dbh->prepare($sql) or die $dbh->errstr. " preparing $sql";
- $sth->execute($queueid) or die $sth->errstr. " executing $sql";
-
- $sth->fetchrow_arrayref->[0];
-
-}
-
-sub baseurl {
- #my $self = shift;
- $external_url;
+ 'Ticket/Display.html?id='.$ticketnum;
}
1;
diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm
index 8fce918e0..00398230f 100644
--- a/FS/FS/TicketSystem/RT_Internal.pm
+++ b/FS/FS/TicketSystem/RT_Internal.pm
@@ -16,13 +16,32 @@ sub sql_num_customer_tickets {
)";
}
-sub baseurl {
- #my $self = shift;
- if ( $RT::URI::freeside::URL ) {
- $RT::URI::freeside::URL. 'rt/';
- } else {
- 'http://you_need_to_set_RT_URI_freeside_URL_in_SiteConfig.pm/';
- }
+sub num_customer_tickets {
+ my( $self, $custnum, $priority ) = ( shift, shift, shift );
+ $self->SUPER::num_customer_tickets( $custnum, $priority, dbh );
+}
+
+sub customer_tickets {
+ my( $self, $custnum, $limit, $priority ) = ( shift, shift, shift, shift );
+ $self->SUPER::customer_tickets( $custnum, $limit, $priority, dbh );
+}
+
+sub href_customer_tickets {
+ my $self = shift;
+ # well, 2 is wrong here but will have to do for now
+ popurl(2).'rt/'. $self->SUPER::href_customer_tickets(@_);
+}
+
+sub href_new_ticket {
+ my $self = shift;
+ # well, 2 is wrong here but will have to do for now
+ popurl(2).'rt/'. $self->SUPER::href_new_ticket(@_);
+}
+
+sub href_ticket {
+ my $self = shift;
+ # well, 2 is wrong here but will have to do for now
+ popurl(2).'rt/'. $self->SUPER::href_ticket(@_);
}
1;
diff --git a/FS/FS/UI/Base.pm b/FS/FS/UI/Base.pm
new file mode 100644
index 000000000..bbeb9e171
--- /dev/null
+++ b/FS/FS/UI/Base.pm
@@ -0,0 +1,194 @@
+package FS::UI::Base;
+
+use strict;
+use vars qw ( @ISA );
+use FS::Record qw( fields qsearch );
+
+@ISA = ( $FS::UI::Base::_lock );
+
+=head1 NAME
+
+FS::UI::Base - Base class for all user-interface objects
+
+=head1 SYNOPSIS
+
+ use FS::UI::SomeInterface;
+ use FS::UI::some_table;
+
+ $interface = new FS::UI::some_table;
+
+ $error = $interface->browse;
+ $error = $interface->search;
+ $error = $interface->view;
+ $error = $interface->edit;
+ $error = $interface->process;
+
+=head1 DESCRIPTION
+
+An FS::UI::Base object represents a user interface object. FS::UI::Base
+is intended as a base class for table-specfic classes to inherit from, i.e.
+FS::UI::cust_main. The simplest case, which will provide a default UI for your
+new table, is as follows:
+
+ package FS::UI::table_name;
+ use vars qw ( @ISA );
+ use FS::UI::Base;
+ @ISA = qw( FS::UI::Base );
+ sub db_table { 'table_name'; }
+
+Currently available interfaces are:
+ FS::UI::Gtk, an X-Windows UI implemented using the Gtk+ toolkit
+ FS::UI::CGI, a web interface implemented using CGI.pm, etc.
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+=cut
+
+=item browse
+
+=cut
+
+sub browse {
+ my $self = shift;
+
+ my @fields = $self->list_fields;
+
+ #begin browse-specific stuff
+
+ $self->title( "Browse ". $self->db_names ) unless $self->title;
+ my @records = qsearch ( $self->db_table, {} );
+
+ #end browse-specific stuff
+
+ $self->addwidget ( new FS::UI::_Text ( $self->db_description ) );
+
+ my @header = $self->list_header;
+ my @headerspan = $self->list_headerspan;
+ my %callback = $self->db_callback;
+
+ my $columns;
+
+ my $table = new FS::UI::_Tableborder (
+ 'rows' => 1 + scalar(@records),
+ 'columns' => $columns || scalar(@fields),
+ );
+
+ my $c = 0;
+ foreach my $header ( @header ) {
+ my $headerspan = shift(@headerspan) || 1;
+ $table->attach(
+ 0, $c, new FS::UI::_Text ( $header ), 1, $headerspan
+ );
+ $c += $headerspan;
+ }
+
+ my $r = 1;
+
+ foreach my $record ( @records ) {
+ $c = 0;
+ foreach my $field ( @fields ) {
+ my $value = $record->getfield($field);
+ my $widget;
+ if ( $callback{$field} ) {
+ $widget = &{ $callback{$field} }( $value, $record );
+ } else {
+ $widget = new FS::UI::_Text ( $value );
+ }
+ $table->attach( $r, $c++, $widget, 1, 1 );
+ }
+ $r++;
+ }
+
+ $self->addwidget( $table );
+
+ $self->activate;
+
+}
+
+=item title
+
+=cut
+
+sub title {
+ my $self = shift;
+ my $value = shift;
+ if ( defined($value) ) {
+ $self->{'title'} = $value;
+ } else {
+ $self->{'title'};
+ }
+}
+
+=item addwidget
+
+=cut
+
+sub addwidget {
+ my $self = shift;
+ my $widget = shift;
+ push @{ $self->{'Widgets'} }, $widget;
+}
+
+#fallback methods
+
+sub db_description {}
+
+sub db_name {}
+
+sub db_names {
+ my $self = shift;
+ $self->db_name. 's';
+}
+
+sub list_fields {
+ my $self = shift;
+ fields( $self->db_table );
+}
+
+sub list_header {
+ my $self = shift;
+ $self->list_fields
+}
+
+sub list_headerspan {
+ my $self = shift;
+ map 1, $self->list_header;
+}
+
+sub db_callback {}
+
+=back
+
+=head1 VERSION
+
+$Id: Base.pm,v 1.1 1999-08-04 09:03:53 ivan Exp $
+
+=head1 BUGS
+
+This documentation is incomplete.
+
+There should be some sort of per-(freeside)-user preferences and the ability
+for specific FS::UI:: modules to put their own values there as well.
+
+=head1 SEE ALSO
+
+L<FS::UI::Gtk>, L<FS::UI::CGI>
+
+=head1 HISTORY
+
+$Log: Base.pm,v $
+Revision 1.1 1999-08-04 09:03:53 ivan
+initial checkin of module files for proper perl installation
+
+Revision 1.1 1999/01/20 09:30:36 ivan
+skeletal cross-UI UI code.
+
+
+=cut
+
+1;
+
diff --git a/FS/FS/UI/CGI.pm b/FS/FS/UI/CGI.pm
new file mode 100644
index 000000000..ae87d1375
--- /dev/null
+++ b/FS/FS/UI/CGI.pm
@@ -0,0 +1,239 @@
+package FS::UI::CGI;
+
+use strict;
+use CGI;
+#use CGI::Switch; #when FS::UID user and preference callback stuff is fixed
+use CGI::Carp qw(fatalsToBrowser);
+use HTML::Table;
+use FS::UID qw(adminsuidsetup);
+#use FS::Record qw( qsearch fields );
+
+die "Can't initialize CGI interface; $FS::UI::Base::_lock used"
+ if $FS::UI::Base::_lock;
+$FS::UI::Base::_lock = "FS::UI::CGI";
+
+=head1 NAME
+
+FS::UI::CGI - Base class for CGI user-interface objects
+
+=head1 SYNOPSIS
+
+ use FS::UI::CGI;
+ use FS::UI::some_table;
+
+ $interface = new FS::UI::some_table;
+
+ $error = $interface->browse;
+ $error = $interface->search;
+ $error = $interface->view;
+ $error = $interface->edit;
+ $error = $interface->process;
+
+=head1 DESCRIPTION
+
+An FS::UI::CGI object represents a CGI interface object.
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+=cut
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = { @_ };
+
+ $self->{'_cgi'} = new CGI;
+ $self->{'_user'} = $self->{'_cgi'}->remote_user;
+ $self->{'_dbh'} = FS::UID::adminsuidsetup $self->{'_user'};
+
+ bless ( $self, $class);
+}
+
+sub activate {
+ my $self = shift;
+ print $self->_header,
+ join ( "<BR>", map $_->sprint, @{ $self->{'Widgets'} } ),
+ $self->_footer,
+ ;
+}
+
+=item _header
+
+=cut
+
+sub _header {
+ my $self = shift;
+ my $cgi = $self->{'_cgi'};
+
+ $cgi->header( '-expires' => 'now' ), '<HTML>',
+ '<HEAD><TITLE>', $self->title, '</TITLE></HEAD>',
+ '<BODY BGCOLOR="#ffffff">',
+ '<FONT COLOR="#ff0000" SIZE=7>', $self->title, '</FONT><BR><BR>',
+ ;
+}
+
+=item _footer
+
+=cut
+
+sub _footer {
+ "</BODY></HTML>";
+}
+
+=item interface
+
+Returns the string `CGI'. Useful for the author of a table-specific UI class
+to conditionally specify certain behaviour.
+
+=cut
+
+sub interface { 'CGI'; }
+
+=back
+
+=cut
+
+package FS::UI::_Widget;
+
+use vars qw( $AUTOLOAD );
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = { @_ };
+ bless ( $self, $class );
+}
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $value = shift;
+ my($field)=$AUTOLOAD;
+ $field =~ s/.*://;
+ if ( defined($value) ) {
+ $self->{$field} = $value;
+ } else {
+ $self->{$field};
+ }
+}
+
+package FS::UI::_Text;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Widget);
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ $self->{'_text'} = shift;
+ bless ( $self, $class );
+}
+
+sub sprint {
+ my $self = shift;
+ $self->{'_text'};
+}
+
+package FS::UI::_Link;
+
+use vars qw ( @ISA $BASE_URL );
+
+@ISA = qw ( FS::UI::_Widget);
+$BASE_URL = "http://rootwood.sisd.com/freeside";
+
+sub sprint {
+ my $self = shift;
+ my $table = $self->{'table'};
+ my $method = $self->{'method'};
+
+ # i will be cleaned up when we're done moving from the old webinterface!
+ my @arg = @{$self->{'arg'}};
+ my $yuck = join( "&", @arg);
+ qq(<A HREF="$BASE_URL/$method/$table.cgi?$yuck">). $self->{'text'}. "<\A>";
+}
+
+package FS::UI::_Table;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Widget);
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class eq $proto ? { @_ } : $proto;
+ bless ( $self, $class );
+ $self->{'_table'} = new HTML::Table ( $self->rows, $self->columns );
+ $self;
+}
+
+sub attach {
+ my $self = shift;
+ my ( $row, $column, $widget, $rowspan, $colspan ) = @_;
+ $self->{"_table"}->setCell( $row+1, $column+1, $widget->sprint );
+ $self->{"_table"}->setCellRowSpan( $row+1, $column+1, $rowspan ) if $rowspan;
+ $self->{"_table"}->setCellColSpan( $row+1, $column+1, $colspan ) if $colspan;
+}
+
+sub sprint {
+ my $self = shift;
+ $self->{'_table'}->getTable;
+}
+
+package FS::UI::_Tableborder;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Table );
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class eq $proto ? { @_ } : $proto;
+ bless ( $self, $class );
+ $self->SUPER::new(@_);
+ $self->{'_table'}->setBorder;
+ $self;
+}
+
+=head1 VERSION
+
+$Id: CGI.pm,v 1.1 1999-08-04 09:03:53 ivan Exp $
+
+=head1 BUGS
+
+This documentation is incomplete.
+
+In _Tableborder, headers should be links that sort on their fields.
+
+_Link uses a constant $BASE_URL
+
+_Link passes the arguments as a manually-constructed GET string instead
+of POSTing, for compatability while the web interface is upgraded. Once
+this is done it should pass arguements properly (i.e. as a POST, 8-bit clean)
+
+Still some small bits of widget code same as FS::UI::Gtk.
+
+=head1 SEE ALSO
+
+L<FS::UI::Base>
+
+=head1 HISTORY
+
+$Log: CGI.pm,v $
+Revision 1.1 1999-08-04 09:03:53 ivan
+initial checkin of module files for proper perl installation
+
+Revision 1.1 1999/01/20 09:30:36 ivan
+skeletal cross-UI UI code.
+
+
+=cut
+
+1;
+
diff --git a/FS/FS/UI/Gtk.pm b/FS/FS/UI/Gtk.pm
new file mode 100644
index 000000000..507a29361
--- /dev/null
+++ b/FS/FS/UI/Gtk.pm
@@ -0,0 +1,224 @@
+package FS::UI::Gtk;
+
+use strict;
+use Gtk;
+use FS::UID qw(adminsuidsetup);
+
+die "Can't initialize Gtk interface; $FS::UI::Base::_lock used"
+ if $FS::UI::Base::_lock;
+$FS::UI::Base::_lock = "FS::UI::Gtk";
+
+=head1 NAME
+
+FS::UI::Gtk - Base class for Gtk user-interface objects
+
+=head1 SYNOPSIS
+
+ use FS::UI::Gtk;
+ use FS::UI::some_table;
+
+ $interface = new FS::UI::some_table;
+
+ $error = $interface->browse;
+ $error = $interface->search;
+ $error = $interface->view;
+ $error = $interface->edit;
+ $error = $interface->process;
+
+=head1 DESCRIPTION
+
+An FS::UI::Gtk object represents a Gtk user interface object.
+
+=head1 METHODS
+
+=over 4
+
+=item new
+
+=cut
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = { @_ };
+
+ bless ( $self, $class );
+
+ $self->{'_user'} = 'ivan'; #Pop up login window?
+ $self->{'_dbh'} = FS::UID::adminsuidsetup $self->{'_user'};
+
+
+
+ $self;
+}
+
+sub activate {
+ my $self = shift;
+
+ my $vbox = new Gtk::VBox ( 0, 4 );
+
+ foreach my $widget ( @{ $self->{'Widgets'} } ) {
+ $widget->_gtk->show;
+ $vbox->pack_start ( $widget->_gtk, 1, 1, 4 );
+ }
+ $vbox->show;
+
+ my $window = new Gtk::Window "toplevel";
+ $self->{'_gtk'} = $window;
+ $window->set_title( $self->title );
+ $window->add ( $vbox );
+ $window->show;
+ main Gtk;
+}
+
+=item interface
+
+Returns the string `Gtk'. Useful for the author of a table-specific UI class
+to conditionally specify certain behaviour.
+
+=cut
+
+sub interface { 'Gtk'; }
+
+=back
+
+=cut
+
+package FS::UI::_Widget;
+
+use vars qw( $AUTOLOAD );
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = { @_ };
+ bless ( $self, $class );
+}
+
+sub _gtk {
+ my $self = shift;
+ $self->{'_gtk'};
+}
+
+sub AUTOLOAD {
+ my $self = shift;
+ my $value = shift;
+ my($field)=$AUTOLOAD;
+ $field =~ s/.*://;
+ if ( defined($value) ) {
+ $self->{$field} = $value;
+ } else {
+ $self->{$field};
+ }
+}
+
+package FS::UI::_Text;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Widget );
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ $self->{'_gtk'} = new Gtk::Label ( shift );
+ bless ( $self, $class );
+}
+
+package FS::UI::_Link;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Widget );
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = { @_ };
+ $self->{'_gtk'} = new_with_label Gtk::Button ( $self->{'text'} );
+ $self->{'_gtk'}->signal_connect( 'clicked', sub {
+ print "STUB: (Gtk) FS::UI::_Link";
+ }, "hi", "there" );
+ bless ( $self, $class );
+}
+
+
+package FS::UI::_Table;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Widget );
+
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = { @_ };
+ bless ( $self, $class );
+
+ $self->{'_gtk'} = new Gtk::Table (
+ $self->rows,
+ $self->columns,
+ 0, #homogeneous
+ );
+
+ $self;
+}
+
+sub attach {
+ my $self = shift;
+ my ( $row, $column, $widget, $rowspan, $colspan ) = @_;
+ $rowspan ||= 1;
+ $colspan ||= 1;
+ $self->_gtk->attach_defaults(
+ $widget->_gtk,
+ $column,
+ $column + $colspan,
+ $row,
+ $row + $rowspan,
+ );
+ $widget->_gtk->show;
+}
+
+package FS::UI::_Tableborder;
+
+use vars qw ( @ISA );
+
+@ISA = qw ( FS::UI::_Table );
+
+=head1 VERSION
+
+$Id: Gtk.pm,v 1.1 1999-08-04 09:03:53 ivan Exp $
+
+=head1 BUGS
+
+This documentation is incomplete.
+
+_Tableborder is just a _Table now. _Tableborders should scroll (but not the
+headers) and need and need more decoration. (data in white section ala gtksql
+and sliding field widths) headers should be buttons that callback to sort on
+their fields.
+
+There should be a persistant, per-(freeside)-user store for window positions
+and sizes and sort fields etc (see L<FS::UI::CGI/BUGS>.
+
+Still some small bits of widget code same as FS::UI::CGI.
+
+=head1 SEE ALSO
+
+L<FS::UI::Base>
+
+=head1 HISTORY
+
+$Log: Gtk.pm,v $
+Revision 1.1 1999-08-04 09:03:53 ivan
+initial checkin of module files for proper perl installation
+
+Revision 1.1 1999/01/20 09:30:36 ivan
+skeletal cross-UI UI code.
+
+
+=cut
+
+1;
+
diff --git a/FS/FS/UI/Web.pm b/FS/FS/UI/Web.pm
deleted file mode 100644
index 49e3fbf7e..000000000
--- a/FS/FS/UI/Web.pm
+++ /dev/null
@@ -1,267 +0,0 @@
-package FS::UI::Web;
-
-use vars qw($DEBUG);
-use FS::Conf;
-use FS::Record qw(dbdef);
-
-#use vars qw(@ISA);
-#use FS::UI
-#@ISA = qw( FS::UI );
-
-use Date::Parse;
-sub parse_beginning_ending {
- my($cgi) = @_;
-
- my $beginning = 0;
- if ( $cgi->param('begin') =~ /^(\d+)$/ ) {
- $beginning = $1;
- } elsif ( $cgi->param('beginning') =~ /^([ 0-9\-\/]{1,64})$/ ) {
- $beginning = str2time($1) || 0;
- }
-
- my $ending = 4294967295; #2^32-1
- if ( $cgi->param('end') =~ /^(\d+)$/ ) {
- $ending = $1 - 1;
- } elsif ( $cgi->param('ending') =~ /^([ 0-9\-\/]{1,64})$/ ) {
- #probably need an option to turn off the + 86399
- $ending = str2time($1) + 86399;
- }
-
- ( $beginning, $ending );
-}
-
-###
-# cust_main report methods
-###
-
-=item cust_header
-
-Returns an array of customer information headers according to the
-B<cust-fields> configuration setting.
-
-=cut
-
-use vars qw( @cust_fields );
-
-sub cust_sql_fields {
- my @fields = qw( last first company );
- push @fields, map "ship_$_", @fields
- if dbdef->table('cust_main')->column('ship_last');
- map "cust_main.$_", @fields;
-}
-
-sub cust_header {
-
- warn "FS::svc_Common::cust_header called"
- if $DEBUG;
-
- my $conf = new FS::Conf;
-
- my %header2method = (
- 'Customer' => 'name',
- 'Cust#' => 'custnum',
- 'Name' => 'contact',
- 'Company' => 'company',
- '(bill) Customer' => 'name',
- '(service) Customer' => 'ship_name',
- '(bill) Name' => 'contact',
- '(service) Name' => 'ship_contact',
- '(bill) Company' => 'company',
- '(service) Company' => 'ship_company',
- );
-
- my @cust_header;
- if ( $conf->exists('cust-fields')
- && $conf->config('cust-fields') =~ /^([\w \|\#\(\)]+):/
- )
- {
- warn " found cust-fields configuration value"
- if $DEBUG;
-
- my $cust_fields = $1;
- @cust_header = split(/ \| /, $cust_fields);
- @cust_fields = map { $header2method{$_} } @cust_header;
- } else {
- warn " no cust-fields configuration value found; using default 'Customer'"
- if $DEBUG;
- @cust_header = ( 'Customer' );
- @cust_fields = ( 'name' );
- }
-
- #my $svc_x = shift;
- @cust_header;
-}
-
-=item cust_fields
-
-Given a svc_ object that contains fields from cust_main (say, from a
-JOINed search. See httemplate/search/svc_* for examples), returns an array
-of customer information according to the <B>cust-fields</B> configuration
-setting, or "(unlinked)" if this service is not linked to a customer.
-
-=cut
-
-sub cust_fields {
- my $svc_x = shift;
- warn "FS::svc_Common::cust_fields called for $svc_x ".
- "(cust_fields: @cust_fields)"
- if $DEBUG > 1;
-
- cust_header() unless @cust_fields;
-
- my $seen_unlinked = 0;
- map {
- if ( $svc_x->custnum ) {
- warn " $svc_x -> $_"
- if $DEBUG > 1;
- $svc_x->$_(@_);
- } else {
- warn " ($svc_x unlinked)"
- if $DEBUG > 1;
- $seen_unlinked++ ? '' : '(unlinked)';
- }
- } @cust_fields;
-}
-
-###
-# begin JSRPC code...
-###
-
-package FS::UI::Web::JSRPC;
-
-use strict;
-use vars qw($DEBUG);
-use Storable qw(nfreeze);
-use MIME::Base64;
-use JSON;
-use FS::UID;
-use FS::Record qw(qsearchs);
-use FS::queue;
-
-$DEBUG = 0;
-
-sub new {
- my $class = shift;
- my $self = {
- env => {},
- job => shift,
- cgi => shift,
- };
-
- bless $self, $class;
-
- die "CGI object required as second argument" unless $self->{'cgi'};
-
- return $self;
-}
-
-sub process {
-
- my $self = shift;
-
- my $cgi = $self->{'cgi'};
-
- # XXX this should parse JSON foo and build a proper data structure
- my @args = $cgi->param('arg');
-
- #work around konqueror bug!
- @args = map { s/\x00$//; $_; } @args;
-
- my $sub = $cgi->param('sub'); #????
-
- warn "FS::UI::Web::JSRPC::process:\n".
- " cgi=$cgi\n".
- " sub=$sub\n".
- " args=".join(', ',@args)."\n"
- if $DEBUG;
-
- if ( $sub eq 'start_job' ) {
-
- $self->start_job(@args);
-
- } elsif ( $sub eq 'job_status' ) {
-
- $self->job_status(@args);
-
- }
-
-}
-
-sub start_job {
- my $self = shift;
-
- warn "FS::UI::Web::start_job: ". join(', ', @_) if $DEBUG;
-# my %param = @_;
- my %param = ();
- while ( @_ ) {
- my( $field, $value ) = splice(@_, 0, 2);
- unless ( exists( $param{$field} ) ) {
- $param{$field} = $value;
- } elsif ( ! ref($param{$field}) ) {
- $param{$field} = [ $param{$field}, $value ];
- } else {
- push @{$param{$field}}, $value;
- }
- }
- warn "FS::UI::Web::start_job\n".
- join('', map {
- if ( ref($param{$_}) ) {
- " $_ => [ ". join(', ', @{$param{$_}}). " ]\n";
- } else {
- " $_ => $param{$_}\n";
- }
- } keys %param )
- if $DEBUG;
-
- #first get the CGI params shipped off to a job ASAP so an id can be returned
- #to the caller
-
- my $job = new FS::queue { 'job' => $self->{'job'} };
-
- #too slow to insert all the cgi params as individual args..,?
- #my $error = $queue->insert('_JOB', $cgi->Vars);
-
- #warn 'froze string of size '. length(nfreeze(\%param)). " for job args\n"
- # if $DEBUG;
-
- my $error = $job->insert( '_JOB', encode_base64(nfreeze(\%param)) );
-
- if ( $error ) {
- $error; #this doesn't seem to be handled well,
- # will trigger "illegal jobnum" below?
- # (should never be an error inserting the job, though, only thing
- # would be Pg f%*kage)
- } else {
- $job->jobnum;
- }
-
-}
-
-sub job_status {
- my( $self, $jobnum ) = @_; #$url ???
-
- sleep 1; # XXX could use something better...
-
- my $job;
- if ( $jobnum =~ /^(\d+)$/ ) {
- $job = qsearchs('queue', { 'jobnum' => $jobnum } );
- } else {
- die "FS::UI::Web::job_status: illegal jobnum $jobnum\n";
- }
-
- my @return;
- if ( $job && $job->status ne 'failed' ) {
- @return = ( 'progress', $job->statustext );
- } elsif ( !$job ) { #handle job gone case : job sucessful
- # so close popup, redirect parent window...
- @return = ( 'complete' );
- } else {
- @return = ( 'error', $job ? $job->statustext : $jobnum );
- }
-
- objToJson(\@return);
-
-}
-
-1;
-
diff --git a/FS/FS/UI/agent.pm b/FS/FS/UI/agent.pm
new file mode 100644
index 000000000..ce9744a55
--- /dev/null
+++ b/FS/FS/UI/agent.pm
@@ -0,0 +1,62 @@
+package FS::UI::agent;
+
+use strict;
+use vars qw ( @ISA );
+use FS::UI::Base;
+use FS::Record qw( qsearchs );
+use FS::agent;
+use FS::agent_type;
+
+@ISA = qw ( FS::UI::Base );
+
+sub db_table { 'agent' };
+
+sub db_name { 'Agent' };
+
+sub db_description { <<END;
+Agents are resellers of your service. Agents may be limited to a subset of your
+full offerings (via their type).
+END
+}
+
+sub list_fields {
+ 'agentnum',
+ 'typenum',
+# 'freq',
+# 'prog',
+; }
+
+sub list_header {
+ 'Agent',
+ 'Type',
+# 'Freq (n/a)',
+# 'Prog (n/a)',
+; }
+
+sub db_callback {
+ 'agentnum' =>
+ sub {
+ my ( $agentnum, $record ) = @_;
+ my $agent = $record->agent;
+ new FS::UI::_Link (
+ 'table' => 'agent',
+ 'method' => 'edit',
+ 'arg' => [ $agentnum ],
+ 'text' => "$agentnum: $agent",
+ );
+ },
+ 'typenum' =>
+ sub {
+ my $typenum = shift;
+ my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } );
+ my $atype = $agent_type->atype;
+ new FS::UI::_Link (
+ 'table' => 'agent_type',
+ 'method' => 'edit',
+ 'arg' => [ $typenum ],
+ 'text' => "$typenum: $atype"
+ );
+ },
+}
+
+1;
diff --git a/FS/FS/UID.pm b/FS/FS/UID.pm
index c0c9f7af4..3d893ee2f 100644
--- a/FS/FS/UID.pm
+++ b/FS/FS/UID.pm
@@ -98,7 +98,7 @@ sub forksuidsetup {
}
sub myconnect {
- DBI->connect( getsecrets, {'AutoCommit' => 0, 'ChopBlanks' => 1, } )
+ $dbh = DBI->connect( getsecrets, {'AutoCommit' => 0, 'ChopBlanks' => 1, } )
or die "DBI->connect error: $DBI::errstr\n";
}
diff --git a/FS/FS/XMLRPC.pm b/FS/FS/XMLRPC.pm
deleted file mode 100644
index 84f3e4141..000000000
--- a/FS/FS/XMLRPC.pm
+++ /dev/null
@@ -1,165 +0,0 @@
-package FS::XMLRPC;
-
-use strict;
-use vars qw( @ISA $DEBUG );
-use Frontier::RPC2;
-
-# Instead of 'use'ing freeside modules on the fly below, just preload them now.
-use FS;
-use FS::CGI;
-use FS::Conf;
-use FS::Record;
-use FS::cust_main;
-
-@ISA = qw( );
-
-$DEBUG = 1;
-
-=head1 NAME
-
-FS::XMLRPC - Object methods for handling XMLRPC requests
-
-=head1 SYNOPSIS
-
- use FS::XMLRPC;
-
- $xmlrpc = new FS::XMLRPC;
-
- ($error, $response_xml) = $xmlrpc->serve($request_xml);
-
-=head1 DESCRIPTION
-
-The FS::XMLRPC object is a mechanisim to access read-only data from freeside's subroutines. It does not, at least not at this point, give you the ability to access methods of freeside objects remotely. It can, however, be used to call subroutines such as FS::cust_main::smart_search and FS::Record::qsearch.
-
-See the serve method below for calling syntax.
-
-=head1 METHODS
-
-=over 4
-
-=item new
-
-Provides a FS::XMLRPC object used to handle incoming XMLRPC requests.
-
-=cut
-
-sub new {
-
- my $class = shift;
- my $self = {};
- bless($self, $class);
-
- $self->{_coder} = new Frontier::RPC2;
-
- return $self;
-
-}
-
-=item serve REQUEST_XML_SCALAR
-
-The serve method takes a scalar containg an XMLRPC request for one of freeside's subroutines (not object methods). Parameters passed in the 'methodCall' will be passed as a list to the subroutine untouched. The return value of the called subroutine _must_ be a freeside object reference (eg. qsearchs) or a list of freeside object references (eg. qsearch, smart_search), _and_, the object(s) returned must support the hashref method. This will be checked first by calling UNIVERSAL::can('FS::class::subroutine', 'hashref').
-
-Return value is an XMLRPC methodResponse containing the results of the call. The result of the subroutine call itself will be coded in the methodResponse as an array of structs, regardless of whether there was many or a single object returned. In other words, after you decode the response, you'll always have an array.
-
-=cut
-
-sub serve {
-
- my ($self, $request_xml) = (shift, shift);
- my $response_xml;
-
- my $coder = $self->{_coder};
- my $call = $coder->decode($request_xml);
-
- warn "Got methodCall with method_name='" . $call->{method_name} . "'"
- if $DEBUG;
-
- $response_xml = $coder->encode_response(&_serve($call->{method_name}, $call->{value}));
-
- return ('', $response_xml);
-
-}
-
-sub _serve { #Subroutine, not method
-
- my ($method_name, $params) = (shift, shift);
-
- use Data::Dumper;
-
- #die 'Called _serve without parameters' unless ref($params) eq 'ARRAY';
- $params = [] unless (ref($params) eq 'ARRAY');
-
- if ($method_name =~ /^(\w+)\.(\w+)/) {
-
- #my ($class, $sub) = split(/\./, $method_name);
- my ($class, $sub) = ($1, $2);
- my $fssub = "FS::${class}::${sub}";
- warn "fssub: ${fssub}" if $DEBUG;
- warn "params: " . Dumper($params) if $DEBUG;
-
- my @result;
-
- if ($class eq 'Conf') { #Special case for FS::Conf because we need an obj.
-
- if ($sub eq 'config') {
- my $conf = new FS::Conf;
- @result = ($conf->config(@$params));
- } else {
- warn "FS::XMLRPC: Can't call undefined subroutine '${fssub}'";
- }
-
- } else {
-
- unless (UNIVERSAL::can("FS::${class}", $sub)) {
- warn "FS::XMLRPC: Can't call undefined subroutine '${fssub}'";
- # Should we encode an error in the response,
- # or just break silently to the remote caller and complain locally?
- return [];
- }
-
- eval {
- no strict 'refs';
- my $fssub = "FS::${class}::${sub}";
- @result = (&$fssub(@$params));
- };
-
- if ($@) {
- warn "FS::XMLRPC: Error while calling '${fssub}': $@";
- return [];
- }
-
- }
-
- warn Dumper(@result);
-
- if (grep { UNIVERSAL::can($_, 'hashref') ? 0 : 1 } @result) {
- #warn "FS::XMLRPC: One or more objects returned from '${fssub}' doesn't " .
- # "support the 'hashref' method.";
-
- # If they're not FS::Record decendants, just return the results unmap'd?
- # This is more flexible, but possibly more error-prone.
- return [ @result ];
- } else {
- return [ map { $_->hashref } @result ];
- }
- } elsif ($method_name eq 'version') {
- return [ $FS::VERSION ];
- } # else...
-
- warn "Unhandle XMLRPC request '${method_name}'";
- return [];
-
-}
-
-=head1 BUGS
-
-Probably lots.
-
-=head1 SEE ALSO
-
-L<Frontier::RPC2>.
-
-=cut
-
-1;
-
diff --git a/FS/FS/agent.pm b/FS/FS/agent.pm
index 83f0ce5b5..a9e41a666 100644
--- a/FS/FS/agent.pm
+++ b/FS/FS/agent.pm
@@ -2,13 +2,9 @@ package FS::agent;
use strict;
use vars qw( @ISA );
-#use Crypt::YAPassGen;
use FS::Record qw( dbh qsearch qsearchs );
use FS::cust_main;
-use FS::cust_pkg;
use FS::agent_type;
-use FS::reg_code;
-use FS::TicketSystem;
@ISA = qw( FS::Record );
@@ -168,18 +164,6 @@ sub pkgpart_hashref {
$self->agent_type->pkgpart_hashref;
}
-=item ticketing_queue
-
-Returns the queue name corresponding with the id from the I<ticketing_queueid>
-field, or the empty string.
-
-=cut
-
-sub ticketing_queue {
- my $self = shift;
- FS::TicketSystem->queue($self->ticketing_queueid);
-};
-
=item num_prospect_cust_main
Returns the number of prospects (customers with no packages ever ordered) for
@@ -193,9 +177,10 @@ sub num_prospect_cust_main {
sub num_sql {
my( $self, $sql ) = @_;
- my $statement = "SELECT COUNT(*) FROM cust_main WHERE agentnum = ? AND $sql";
- my $sth = dbh->prepare($statement) or die dbh->errstr." preparing $statement";
- $sth->execute($self->agentnum) or die $sth->errstr. "executing $statement";
+ my $sth = dbh->prepare(
+ "SELECT COUNT(*) FROM cust_main WHERE agentnum = ? AND $sql"
+ ) or die dbh->errstr;
+ $sth->execute($self->agentnum) or die $sth->errstr;
$sth->fetchrow_arrayref->[0];
}
@@ -279,122 +264,6 @@ sub cancel_cust_main {
shift->cust_main_sql(FS::cust_main->cancel_sql);
}
-=item num_active_cust_pkg
-
-Returns the number of active customer packages for this agent.
-
-=cut
-
-sub num_active_cust_pkg {
- shift->num_pkg_sql(FS::cust_pkg->active_sql);
-}
-
-sub num_pkg_sql {
- my( $self, $sql ) = @_;
- my $statement =
- "SELECT COUNT(*) FROM cust_pkg LEFT JOIN cust_main USING ( custnum )".
- " WHERE agentnum = ? AND $sql";
- my $sth = dbh->prepare($statement) or die dbh->errstr." preparing $statement";
- $sth->execute($self->agentnum) or die $sth->errstr. "executing $statement";
- $sth->fetchrow_arrayref->[0];
-}
-
-=item num_susp_cust_pkg
-
-Returns the number of suspended customer packages for this agent.
-
-=cut
-
-sub num_susp_cust_pkg {
- shift->num_pkg_sql(FS::cust_pkg->susp_sql);
-}
-
-=item num_cancel_cust_pkg
-
-Returns the number of cancelled customer packages for this agent.
-
-=cut
-
-sub num_cancel_cust_pkg {
- shift->num_pkg_sql(FS::cust_pkg->cancel_sql);
-}
-
-=item generate_reg_codes NUM PKGPART_ARRAYREF
-
-Generates the specified number of registration codes, allowing purchase of the
-specified package definitions. Returns an array reference of the newly
-generated codes, or a scalar error message.
-
-=cut
-
-#false laziness w/prepay_credit::generate
-sub generate_reg_codes {
- my( $self, $num, $pkgparts ) = @_;
-
- my @codeset = ( 'A'..'Z' );
-
- 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 @codes = ();
- for ( 1 ... $num ) {
- my $reg_code = new FS::reg_code {
- 'agentnum' => $self->agentnum,
- 'code' => join('', map($codeset[int(rand $#codeset)], (0..7) ) ),
- };
- my $error = $reg_code->insert($pkgparts);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- push @codes, $reg_code->code;
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- \@codes;
-
-}
-
-=item num_reg_code
-
-Returns the number of unused registration codes for this agent.
-
-=cut
-
-sub num_reg_code {
- my $self = shift;
- my $sth = dbh->prepare(
- "SELECT COUNT(*) FROM reg_code WHERE agentnum = ?"
- ) or die dbh->errstr;
- $sth->execute($self->agentnum) or die $sth->errstr;
- $sth->fetchrow_arrayref->[0];
-}
-
-=item num_prepay_credit
-
-Returns the number of unused prepaid cards for this agent.
-
-=cut
-
-sub num_prepay_credit {
- my $self = shift;
- my $sth = dbh->prepare(
- "SELECT COUNT(*) FROM prepay_credit WHERE agentnum = ?"
- ) or die dbh->errstr;
- $sth->execute($self->agentnum) or die $sth->errstr;
- $sth->fetchrow_arrayref->[0];
-}
-
-
=back
=head1 BUGS
diff --git a/FS/FS/agent_payment_gateway.pm b/FS/FS/agent_payment_gateway.pm
deleted file mode 100644
index bd99d0ccd..000000000
--- a/FS/FS/agent_payment_gateway.pm
+++ /dev/null
@@ -1,139 +0,0 @@
-package FS::agent_payment_gateway;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-use FS::payment_gateway;
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::agent_payment_gateway - Object methods for agent_payment_gateway records
-
-=head1 SYNOPSIS
-
- use FS::agent_payment_gateway;
-
- $record = new FS::agent_payment_gateway \%hash;
- $record = new FS::agent_payment_gateway { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::agent_payment_gateway object represents a payment gateway override for
-a specific agent. FS::agent_payment_gateway inherits from FS::Record. The
-following fields are currently supported:
-
-=over 4
-
-=item agentgatewaynum - primary key
-
-=item agentnum -
-
-=item gatewaynum -
-
-=item cardtype -
-
-=item taxclass -
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new override. To add the override 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'agent_payment_gateway'; }
-
-=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 override. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('agentgatewaynum')
- || $self->ut_foreign_key('agentnum', 'agent', 'agentnum')
- || $self->ut_foreign_key('gatewaynum', 'payment_gateway', 'gatewaynum' )
- || $self->ut_textn('cardtype')
- || $self->ut_textn('taxclass')
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=item payment_gateway
-
-=cut
-
-sub payment_gateway {
- my $self = shift;
- qsearchs('payment_gateway', { 'gatewaynum' => $self->gatewaynum } );
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::payment_gateway>, L<FS::agent>, L<FS::Record>, schema.html from the
-base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/banned_pay.pm b/FS/FS/banned_pay.pm
deleted file mode 100644
index 1ad87f508..000000000
--- a/FS/FS/banned_pay.pm
+++ /dev/null
@@ -1,136 +0,0 @@
-package FS::banned_pay;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-use FS::UID qw( getotaker );
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::banned_pay - Object methods for banned_pay records
-
-=head1 SYNOPSIS
-
- use FS::banned_pay;
-
- $record = new FS::banned_pay \%hash;
- $record = new FS::banned_pay { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::banned_pay object represents an banned credit card or ACH account.
-FS::banned_pay inherits from FS::Record. The following fields are currently
-supported:
-
-=over 4
-
-=item bannum - primary key
-
-=item payby - I<CARD> or I<CHEK>
-
-=item payinfo - fingerprint of banned card (base64-encoded MD5 digest)
-
-=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
-L<Time::Local> and L<Date::Parse> for conversion functions.
-
-=item otaker - order taker (assigned automatically, see L<FS::UID>)
-
-=item reason - reason (text)
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new ban. To add the ban 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'banned_pay'; }
-
-=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 ban. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('bannum')
- || $self->ut_enum('payby', [ 'CARD', 'CHEK' ] )
- || $self->ut_text('payinfo')
- || $self->ut_numbern('_date')
- || $self->ut_textn('reason')
- ;
- return $error if $error;
-
- $self->_date(time) unless $self->_date;
-
- $self->otaker(getotaker);
-
- $self->SUPER::check;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/cancel_reason.pm b/FS/FS/cancel_reason.pm
deleted file mode 100644
index 19cc7214e..000000000
--- a/FS/FS/cancel_reason.pm
+++ /dev/null
@@ -1,123 +0,0 @@
-package FS::cancel_reason;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::cancel_reason - Object methods for cancel_reason records
-
-=head1 SYNOPSIS
-
- use FS::cancel_reason;
-
- $record = new FS::cancel_reason \%hash;
- $record = new FS::cancel_reason { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::cancel_reason object represents an cancellation reason.
-FS::cancel_reason inherits from FS::Record. The following fields are
-currently supported:
-
-=over 4
-
-=item reasonnum - primary key
-
-=item reason -
-
-=item disabled - empty or "Y"
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new cancellation reason. To add the reason 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'cancel_reason'; }
-
-=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 reason. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('reasonnum')
- || $self->ut_text('reason')
- || $self->ut_enum('disabled', [ '', 'Y' ] )
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/clientapi_session.pm b/FS/FS/clientapi_session.pm
deleted file mode 100644
index f71a126bd..000000000
--- a/FS/FS/clientapi_session.pm
+++ /dev/null
@@ -1,121 +0,0 @@
-package FS::clientapi_session;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::clientapi_session - Object methods for clientapi_session records
-
-=head1 SYNOPSIS
-
- use FS::clientapi_session;
-
- $record = new FS::clientapi_session \%hash;
- $record = new FS::clientapi_session { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::clientapi_session object represents an FS::ClientAPI session.
-FS::clientapi_session inherits from FS::Record. The following fields are
-currently supported:
-
-=over 4
-
-=item sessionnum - primary key
-
-=item sessionid - session ID
-
-=item namespace - session namespace
-
-=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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'clientapi_session'; }
-
-=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 record. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('primary_key')
- || $self->ut_number('validate_other_fields')
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::ClientAPI>, <FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/clientapi_session_field.pm b/FS/FS/clientapi_session_field.pm
deleted file mode 100644
index bfa487ded..000000000
--- a/FS/FS/clientapi_session_field.pm
+++ /dev/null
@@ -1,126 +0,0 @@
-package FS::clientapi_session_field;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::clientapi_session_field - Object methods for clientapi_session_field records
-
-=head1 SYNOPSIS
-
- use FS::clientapi_session_field;
-
- $record = new FS::clientapi_session_field \%hash;
- $record = new FS::clientapi_session_field { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::clientapi_session_field object represents a FS::ClientAPI session data
-field. FS::clientapi_session_field inherits from FS::Record. The following
-fields are currently supported:
-
-=over 4
-
-=item fieldnum - primary key
-
-=item sessionnum - Base ClientAPI sesison (see L<FS::clientapi_session>)
-
-=item fieldname
-
-=item fieldvalie
-
-=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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'clientapi_session_field'; }
-
-=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 record. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('primary_key')
- || $self->ut_number('validate_other_fields')
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=back
-
-=head1 BUGS
-
-The author forgot to customize this manpage.
-
-=head1 SEE ALSO
-
-L<FS::clientapi_session>, L<FS::ClientAPI>, L<FS::Record>, schema.html from the
-base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm
index 6e3b2b2f8..93c179a2a 100644
--- a/FS/FS/cust_bill.pm
+++ b/FS/FS/cust_bill.pm
@@ -1,20 +1,15 @@
package FS::cust_bill;
use strict;
-use vars qw( @ISA $DEBUG $conf $money_char );
+use vars qw( @ISA $conf $money_char );
use vars qw( $invoice_lines @buf ); #yuck
-use Fcntl qw(:flock); #for spool_csv
-use IPC::Run3;
use Date::Format;
-use Text::Template 1.20;
+use Text::Template;
use File::Temp 0.14;
use String::ShellQuote;
-use HTML::Entities;
-use Locale::Country;
use FS::UID qw( datasrc );
-use FS::Misc qw( send_email send_fax );
use FS::Record qw( qsearch qsearchs );
-use FS::cust_main_Mixin;
+use FS::Misc qw( send_email );
use FS::cust_main;
use FS::cust_bill_pkg;
use FS::cust_credit;
@@ -23,13 +18,8 @@ use FS::cust_pkg;
use FS::cust_credit_bill;
use FS::cust_pay_batch;
use FS::cust_bill_event;
-use FS::part_pkg;
-use FS::cust_bill_pay;
-use FS::part_bill_event;
-@ISA = qw( FS::cust_main_Mixin FS::Record );
-
-$DEBUG = 0;
+@ISA = qw( FS::Record );
#ask FS::UID to run this stuff for us later
FS::UID->install_callback( sub {
@@ -107,13 +97,6 @@ Invoices are normally created by calling the bill method of a customer object
sub table { 'cust_bill'; }
-sub cust_linked { $_[0]->cust_main_custnum; }
-sub cust_unlinked_msg {
- my $self = shift;
- "WARNING: can't find cust_main.custnum ". $self->custnum.
- ' (cust_bill.invnum '. $self->invnum. ')';
-}
-
=item insert
Adds this invoice to the database ("Posts" the invoice). If there is an error,
@@ -236,25 +219,6 @@ sub cust_main {
qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
}
-=item cust_suspend_if_balance_over AMOUNT
-
-Suspends the customer associated with this invoice if the total amount owed on
-this invoice and all older invoices is greater than the specified amount.
-
-Returns a list: an empty list on success or a list of errors.
-
-=cut
-
-sub cust_suspend_if_balance_over {
- my( $self, $amount ) = ( shift, shift );
- my $cust_main = $self->cust_main;
- if ( $cust_main->total_owed_date($self->_date) < $amount ) {
- return ();
- } else {
- $cust_main->suspend;
- }
-}
-
=item cust_credit
Depreciated. See the cust_credited method.
@@ -354,244 +318,15 @@ sub owed {
$balance;
}
-
-=item generate_email PARAMHASH
-
-PARAMHASH can contain the following:
-
-=over 4
-
-=item from => sender address, required
-
-=item tempate => alternate template name, optional
-
-=item print_text => text attachment arrayref, optional
-
-=item subject => email subject, optional
-
-=back
-
-Returns an argument list to be passed to L<FS::Misc::send_email>.
-
-=cut
-
-use MIME::Entity;
-
-sub generate_email {
-
- my $self = shift;
- my %args = @_;
-
- my $me = '[FS::cust_bill::generate_email]';
-
- my %return = (
- 'from' => $args{'from'},
- 'subject' => (($args{'subject'}) ? $args{'subject'} : 'Invoice'),
- );
-
- if (ref($args{'to'} eq 'ARRAY')) {
- $return{'to'} = $args{'to'};
- } else {
- $return{'to'} = [ grep { $_ !~ /^(POST|FAX)$/ }
- $self->cust_main->invoicing_list
- ];
- }
-
- if ( $conf->exists('invoice_html') ) {
-
- warn "$me creating HTML/text multipart message"
- if $DEBUG;
-
- $return{'nobody'} = 1;
-
- my $alternative = build MIME::Entity
- 'Type' => 'multipart/alternative',
- 'Encoding' => '7bit',
- 'Disposition' => 'inline'
- ;
-
- my $data;
- if ( $conf->exists('invoice_email_pdf')
- and scalar($conf->config('invoice_email_pdf_note')) ) {
-
- warn "$me using 'invoice_email_pdf_note' in multipart message"
- if $DEBUG;
- $data = [ map { $_ . "\n" }
- $conf->config('invoice_email_pdf_note')
- ];
-
- } else {
-
- warn "$me not using 'invoice_email_pdf_note' in multipart message"
- if $DEBUG;
- if ( ref($args{'print_text'}) eq 'ARRAY' ) {
- $data = $args{'print_text'};
- } else {
- $data = [ $self->print_text('', $args{'template'}) ];
- }
-
- }
-
- $alternative->attach(
- 'Type' => 'text/plain',
- #'Encoding' => 'quoted-printable',
- 'Encoding' => '7bit',
- 'Data' => $data,
- 'Disposition' => 'inline',
- );
-
- $args{'from'} =~ /\@([\w\.\-]+)/ or $1 = 'example.com';
- my $content_id = join('.', rand()*(2**32), $$, time). "\@$1";
-
- my $path = "$FS::UID::conf_dir/conf.$FS::UID::datasrc";
- my $file;
- if ( defined($args{'_template'}) && length($args{'_template'})
- && -e "$path/logo_". $args{'_template'}. ".png"
- )
- {
- $file = "$path/logo_". $args{'_template'}. ".png";
- } else {
- $file = "$path/logo.png";
- }
-
- my $image = build MIME::Entity
- 'Type' => 'image/png',
- 'Encoding' => 'base64',
- 'Path' => $file,
- 'Filename' => 'logo.png',
- 'Content-ID' => "<$content_id>",
- ;
-
- $alternative->attach(
- 'Type' => 'text/html',
- 'Encoding' => 'quoted-printable',
- 'Data' => [ '<html>',
- ' <head>',
- ' <title>',
- ' '. encode_entities($return{'subject'}),
- ' </title>',
- ' </head>',
- ' <body bgcolor="#e8e8e8">',
- $self->print_html('', $args{'template'}, $content_id),
- ' </body>',
- '</html>',
- ],
- 'Disposition' => 'inline',
- #'Filename' => 'invoice.pdf',
- );
-
- if ( $conf->exists('invoice_email_pdf') ) {
-
- #attaching pdf too:
- # multipart/mixed
- # multipart/related
- # multipart/alternative
- # text/plain
- # text/html
- # image/png
- # application/pdf
-
- my $related = build MIME::Entity 'Type' => 'multipart/related',
- 'Encoding' => '7bit';
-
- #false laziness w/Misc::send_email
- $related->head->replace('Content-type',
- $related->mime_type.
- '; boundary="'. $related->head->multipart_boundary. '"'.
- '; type=multipart/alternative'
- );
-
- $related->add_part($alternative);
-
- $related->add_part($image);
-
- my $pdf = build MIME::Entity $self->mimebuild_pdf('', $args{'template'});
-
- $return{'mimeparts'} = [ $related, $pdf ];
-
- } else {
-
- #no other attachment:
- # multipart/related
- # multipart/alternative
- # text/plain
- # text/html
- # image/png
-
- $return{'content-type'} = 'multipart/related';
- $return{'mimeparts'} = [ $alternative, $image ];
- $return{'type'} = 'multipart/alternative'; #Content-Type of first part...
- #$return{'disposition'} = 'inline';
-
- }
-
- } else {
-
- if ( $conf->exists('invoice_email_pdf') ) {
- warn "$me creating PDF attachment"
- if $DEBUG;
-
- #mime parts arguments a la MIME::Entity->build().
- $return{'mimeparts'} = [
- { $self->mimebuild_pdf('', $args{'template'}) }
- ];
- }
-
- if ( $conf->exists('invoice_email_pdf')
- and scalar($conf->config('invoice_email_pdf_note')) ) {
-
- warn "$me using 'invoice_email_pdf_note'"
- if $DEBUG;
- $return{'body'} = [ map { $_ . "\n" }
- $conf->config('invoice_email_pdf_note')
- ];
-
- } else {
-
- warn "$me not using 'invoice_email_pdf_note'"
- if $DEBUG;
- if ( ref($args{'print_text'}) eq 'ARRAY' ) {
- $return{'body'} = $args{'print_text'};
- } else {
- $return{'body'} = [ $self->print_text('', $args{'template'}) ];
- }
-
- }
-
- }
-
- %return;
-
-}
-
-=item mimebuild_pdf
-
-Returns a list suitable for passing to MIME::Entity->build(), representing
-this invoice as PDF attachment.
-
-=cut
-
-sub mimebuild_pdf {
- my $self = shift;
- (
- 'Type' => 'application/pdf',
- 'Encoding' => 'base64',
- 'Data' => [ $self->print_pdf(@_) ],
- 'Disposition' => 'attachment',
- 'Filename' => 'invoice.pdf',
- );
-}
-
=item send [ TEMPLATENAME [ , AGENTNUM [ , INVOICE_FROM ] ] ]
-Sends this invoice to the destinations configured for this customer: sends
-email, prints and/or faxes. See L<FS::cust_main_invoice>.
+Sends this invoice to the destinations configured for this customer: send
+emails or print. See L<FS::cust_main_invoice>.
TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
AGENTNUM, if specified, means that this invoice will only be sent for customers
-of the specified agent or agent(s). AGENTNUM can be a scalar agentnum (for a
-single agent) or an arrayref of agentnums.
+of the specified agent.
INVOICE_FROM, if specified, overrides the default email invoice From: address.
@@ -600,127 +335,44 @@ INVOICE_FROM, if specified, overrides the default email invoice From: address.
sub send {
my $self = shift;
my $template = scalar(@_) ? shift : '';
- if ( scalar(@_) && $_[0] ) {
- my $agentnums = ref($_[0]) ? shift : [ shift ];
- return 'N/A' unless grep { $_ == $self->cust_main->agentnum } @$agentnums;
- }
-
+ return 'N/A' if scalar(@_) && $_[0] && $self->cust_main->agentnum != shift;
my $invoice_from =
scalar(@_)
? shift
: ( $self->_agent_invoice_from || $conf->config('invoice_from') );
+ my @print_text = $self->print_text('', $template);
my @invoicing_list = $self->cust_main->invoicing_list;
- $self->email($template, $invoice_from)
- if grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list or !@invoicing_list;
-
- $self->print($template)
- if grep { $_ eq 'POST' } @invoicing_list; #postal
-
- $self->fax($template)
- if grep { $_ eq 'FAX' } @invoicing_list; #fax
-
- '';
-
-}
-
-=item email [ TEMPLATENAME [ , INVOICE_FROM ] ]
-
-Emails this invoice.
-
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
-
-INVOICE_FROM, if specified, overrides the default email invoice From: address.
-
-=cut
-
-sub email {
- my $self = shift;
- my $template = scalar(@_) ? shift : '';
- my $invoice_from =
- scalar(@_)
- ? shift
- : ( $self->_agent_invoice_from || $conf->config('invoice_from') );
-
- my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ }
- $self->cust_main->invoicing_list;
-
- #better to notify this person than silence
- @invoicing_list = ($invoice_from) unless @invoicing_list;
-
- my $error = send_email(
- $self->generate_email(
- 'from' => $invoice_from,
- 'to' => [ grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ],
- 'template' => $template,
- )
- );
- die "can't email invoice: $error\n" if $error;
- #die "$error\n" if $error;
-
-}
+ if ( grep { $_ ne 'POST' } @invoicing_list or !@invoicing_list ) { #email
-=item lpr_data [ TEMPLATENAME ]
-
-Returns the postscript or plaintext for this invoice as an arrayref.
-
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
-
-=cut
-
-sub lpr_data {
- my( $self, $template) = @_;
- $conf->exists('invoice_latex')
- ? [ $self->print_ps('', $template) ]
- : [ $self->print_text('', $template) ];
-}
+ #better to notify this person than silence
+ @invoicing_list = ($invoice_from) unless @invoicing_list;
-=item print [ TEMPLATENAME ]
-
-Prints this invoice.
-
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
-
-=cut
-
-sub print {
- my $self = shift;
- my $template = scalar(@_) ? shift : '';
-
- my $lpr = $conf->config('lpr');
+ my $error = send_email(
+ 'from' => $invoice_from,
+ 'to' => [ grep { $_ ne 'POST' } @invoicing_list ],
+ 'subject' => 'Invoice',
+ 'body' => \@print_text,
+ );
+ die "can't email invoice: $error\n" if $error;
+ #die "$error\n" if $error;
- my $outerr = '';
- run3 $lpr, $self->lpr_data($template), \$outerr, \$outerr;
- if ( $? ) {
- $outerr = ": $outerr" if length($outerr);
- die "Error from $lpr (exit status ". ($?>>8). ")$outerr\n";
}
-}
-
-=item fax [ TEMPLATENAME ]
-
-Faxes this invoice.
-
-TEMPLATENAME, if specified, is the name of a suffix for alternate invoices.
-
-=cut
-
-sub fax {
- my $self = shift;
- my $template = scalar(@_) ? shift : '';
-
- die 'FAX invoice destination not (yet?) supported with plain text invoices.'
- unless $conf->exists('invoice_latex');
-
- my $dialstring = $self->cust_main->getfield('fax');
- #Check $dialstring?
+ if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal
+ @print_text = $self->print_ps('', $template)
+ if $conf->config('invoice_latex');
+ my $lpr = $conf->config('lpr');
+ open(LPR, "|$lpr")
+ or die "Can't open pipe to $lpr: $!\n";
+ print LPR @print_text;
+ close LPR
+ or die $! ? "Error closing $lpr: $!\n"
+ : "Exit status $? from $lpr\n";
+ }
- my $error = send_fax( 'docdata' => $self->lpr_data($template),
- 'dialstring' => $dialstring,
- );
- die $error if $error;
+ '';
}
@@ -747,7 +399,7 @@ sub send_if_newest {
$self->send(@_);
}
-=item send_csv OPTION => VALUE, ...
+=item send_csv OPTIONS
Sends invoice as a CSV data-file to a remote host with the specified protocol.
@@ -762,141 +414,7 @@ dir
The file will be named "N-YYYYMMDDHHMMSS.csv" where N is the invoice number
and YYMMDDHHMMSS is a timestamp.
-See L</print_csv> for a description of the output format.
-
-=cut
-
-sub send_csv {
- my($self, %opt) = @_;
-
- #create file(s)
-
- my $spooldir = "/usr/local/etc/freeside/export.". datasrc. "/cust_bill";
- mkdir $spooldir, 0700 unless -d $spooldir;
-
- my $tracctnum = $self->invnum. time2str('-%Y%m%d%H%M%S', time);
- my $file = "$spooldir/$tracctnum.csv";
-
- my ( $header, $detail ) = $self->print_csv(%opt, 'tracctnum' => $tracctnum );
-
- open(CSV, ">$file") or die "can't open $file: $!";
- print CSV $header;
-
- print CSV $detail;
-
- close CSV;
-
- my $net;
- if ( $opt{protocol} eq 'ftp' ) {
- eval "use Net::FTP;";
- die $@ if $@;
- $net = Net::FTP->new($opt{server}) or die @$;
- } else {
- die "unknown protocol: $opt{protocol}";
- }
-
- $net->login( $opt{username}, $opt{password} )
- or die "can't FTP to $opt{username}\@$opt{server}: login error: $@";
-
- $net->binary or die "can't set binary mode";
-
- $net->cwd($opt{dir}) or die "can't cwd to $opt{dir}";
-
- $net->put($file) or die "can't put $file: $!";
-
- $net->quit;
-
- unlink $file;
-
-}
-
-=item spool_csv
-
-Spools CSV invoice data.
-
-Options are:
-
-=over 4
-
-=item format - 'default' or 'billco'
-
-=item dest - if set (to POST, EMAIL or FAX), only sends spools invoices if the customer has the corresponding invoice destinations set (see L<FS::cust_main_invoice>).
-
-=item agent_spools - if set to a true value, will spool to per-agent files rather than a single global file
-
-=back
-
-=cut
-
-sub spool_csv {
- my($self, %opt) = @_;
-
- my $cust_main = $self->cust_main;
-
- if ( $opt{'dest'} ) {
- my %invoicing_list = map { /^(POST|FAX)$/ or 'EMAIL' =~ /^(.*)$/; $1 => 1 }
- $cust_main->invoicing_list;
- return 'N/A' unless $invoicing_list{$opt{'dest'}}
- || ! keys %invoicing_list;
- }
-
- my $spooldir = "/usr/local/etc/freeside/export.". datasrc. "/cust_bill";
- mkdir $spooldir, 0700 unless -d $spooldir;
-
- my $tracctnum = $self->invnum. time2str('-%Y%m%d%H%M%S', time);
-
- my $file =
- "$spooldir/".
- ( $opt{'agent_spools'} ? 'agentnum'.$cust_main->agentnum : 'spool' ).
- ( lc($opt{'format'}) eq 'billco' ? '-header' : '' ) .
- '.csv';
-
- my ( $header, $detail ) = $self->print_csv(%opt, 'tracctnum' => $tracctnum );
-
- open(CSV, ">>$file") or die "can't open $file: $!";
- flock(CSV, LOCK_EX);
- seek(CSV, 0, 2);
-
- print CSV $header;
-
- if ( lc($opt{'format'}) eq 'billco' ) {
-
- flock(CSV, LOCK_UN);
- close CSV;
-
- $file =
- "$spooldir/".
- ( $opt{'agent_spools'} ? 'agentnum'.$cust_main->agentnum : 'spool' ).
- '-detail.csv';
-
- open(CSV,">>$file") or die "can't open $file: $!";
- flock(CSV, LOCK_EX);
- seek(CSV, 0, 2);
- }
-
- print CSV $detail;
-
- flock(CSV, LOCK_UN);
- close CSV;
-
- return '';
-
-}
-
-=item print_csv OPTION => VALUE, ...
-
-Returns CSV data for this invoice.
-
-Options are:
-
-format - 'default' or 'billco'
-
-Returns a list consisting of two scalars. The first is a single line of CSV
-header information for this invoice. The second is one or more lines of CSV
-detail information for this invoice.
-
-If I<format> is not specified or "default", the fields of the CSV file are as
-follows:
+The fields of the CSV file is as follows:
record_type, invnum, custnum, _date, charged, first, last, company, address1, address2, city, state, zip, country, pkg, setup, recur, sdate, edate
@@ -904,13 +422,13 @@ record_type, invnum, custnum, _date, charged, first, last, company, address1, ad
=item record type - B<record_type> is either C<cust_bill> or C<cust_bill_pkg>
-B<record_type> is C<cust_bill> for the initial header line only. The
+If B<record_type> is C<cust_bill>, this is a primary invoice record. The
last five fields (B<pkg> through B<edate>) are irrelevant, and all other
fields are filled in.
-B<record_type> is C<cust_bill_pkg> for detail lines. Only the first two fields
-(B<record_type> and B<invnum>) and the last five fields (B<pkg> through B<edate>)
-are filled in.
+If B<record_type> is C<cust_bill_pkg>, this is a line item record. Only the
+first two fields (B<record_type> and B<invnum>) and the last five fields
+(B<pkg> through B<edate>) are filled in.
=item invnum - invoice number
@@ -950,213 +468,101 @@ are filled in.
=back
-If I<format> is "billco", the fields of the header CSV file are as follows:
-
- +-------------------------------------------------------------------+
- | FORMAT HEADER FILE |
- |-------------------------------------------------------------------|
- | Field | Description | Name | Type | Width |
- | 1 | N/A-Leave Empty | RC | CHAR | 2 |
- | 2 | N/A-Leave Empty | CUSTID | CHAR | 15 |
- | 3 | Transaction Account No | TRACCTNUM | CHAR | 15 |
- | 4 | Transaction Invoice No | TRINVOICE | CHAR | 15 |
- | 5 | Transaction Zip Code | TRZIP | CHAR | 5 |
- | 6 | Transaction Company Bill To | TRCOMPANY | CHAR | 30 |
- | 7 | Transaction Contact Bill To | TRNAME | CHAR | 30 |
- | 8 | Additional Address Unit Info | TRADDR1 | CHAR | 30 |
- | 9 | Bill To Street Address | TRADDR2 | CHAR | 30 |
- | 10 | Ancillary Billing Information | TRADDR3 | CHAR | 30 |
- | 11 | Transaction City Bill To | TRCITY | CHAR | 20 |
- | 12 | Transaction State Bill To | TRSTATE | CHAR | 2 |
- | 13 | Bill Cycle Close Date | CLOSEDATE | CHAR | 10 |
- | 14 | Bill Due Date | DUEDATE | CHAR | 10 |
- | 15 | Previous Balance | BALFWD | NUM* | 9 |
- | 16 | Pmt/CR Applied | CREDAPPLY | NUM* | 9 |
- | 17 | Total Current Charges | CURRENTCHG | NUM* | 9 |
- | 18 | Total Amt Due | TOTALDUE | NUM* | 9 |
- | 19 | Total Amt Due | AMTDUE | NUM* | 9 |
- | 20 | 30 Day Aging | AMT30 | NUM* | 9 |
- | 21 | 60 Day Aging | AMT60 | NUM* | 9 |
- | 22 | 90 Day Aging | AMT90 | NUM* | 9 |
- | 23 | Y/N | AGESWITCH | CHAR | 1 |
- | 24 | Remittance automation | SCANLINE | CHAR | 100 |
- | 25 | Total Taxes & Fees | TAXTOT | NUM* | 9 |
- | 26 | Customer Reference Number | CUSTREF | CHAR | 15 |
- | 27 | Federal Tax*** | FEDTAX | NUM* | 9 |
- | 28 | State Tax*** | STATETAX | NUM* | 9 |
- | 29 | Other Taxes & Fees*** | OTHERTAX | NUM* | 9 |
- +-------+-------------------------------+------------+------+-------+
-
-If I<format> is "billco", the fields of the detail CSV file are as follows:
-
- FORMAT FOR DETAIL FILE
- | | | |
- Field | Description | Name | Type | Width
- 1 | N/A-Leave Empty | RC | CHAR | 2
- 2 | N/A-Leave Empty | CUSTID | CHAR | 15
- 3 | Account Number | TRACCTNUM | CHAR | 15
- 4 | Invoice Number | TRINVOICE | CHAR | 15
- 5 | Line Sequence (sort order) | LINESEQ | NUM | 6
- 6 | Transaction Detail | DETAILS | CHAR | 100
- 7 | Amount | AMT | NUM* | 9
- 8 | Line Format Control** | LNCTRL | CHAR | 2
- 9 | Grouping Code | GROUP | CHAR | 2
- 10 | User Defined | ACCT CODE | CHAR | 15
-
=cut
-sub print_csv {
+sub send_csv {
my($self, %opt) = @_;
-
- eval "use Text::CSV_XS";
- die $@ if $@;
- my $cust_main = $self->cust_main;
+ #part one: create file
- my $csv = Text::CSV_XS->new({'always_quote'=>1});
+ my $spooldir = "/usr/local/etc/freeside/export.". datasrc. "/cust_bill";
+ mkdir $spooldir, 0700 unless -d $spooldir;
- if ( lc($opt{'format'}) eq 'billco' ) {
+ my $file = $spooldir. '/'. $self->invnum. time2str('-%Y%m%d%H%M%S.csv', time);
- my $taxtotal = 0;
- $taxtotal += $_->{'amount'} foreach $self->_items_tax;
+ open(CSV, ">$file") or die "can't open $file: $!";
- my $duedate = '';
- if ( $conf->exists('invoice_default_terms')
- && $conf->config('invoice_default_terms')=~ /^\s*Net\s*(\d+)\s*$/ ) {
- $duedate = time2str("%m/%d/%Y", $self->_date + ($1*86400) );
- }
+ eval "use Text::CSV_XS";
+ die $@ if $@;
- my( $previous_balance, @unused ) = $self->previous; #previous balance
+ my $csv = Text::CSV_XS->new({'always_quote'=>1});
- my $pmt_cr_applied = 0;
- $pmt_cr_applied += $_->{'amount'}
- foreach ( $self->_items_payments, $self->_items_credits ) ;
+ my $cust_main = $self->cust_main;
- my $totaldue = sprintf('%.2f', $self->owed + $previous_balance);
+ $csv->combine(
+ 'cust_bill',
+ $self->invnum,
+ $self->custnum,
+ time2str("%x", $self->_date),
+ sprintf("%.2f", $self->charged),
+ ( map { $cust_main->getfield($_) }
+ qw( first last company address1 address2 city state zip country ) ),
+ map { '' } (1..5),
+ ) or die "can't create csv";
+ print CSV $csv->string. "\n";
+
+ #new charges (false laziness w/print_text)
+ foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
+
+ my($pkg, $setup, $recur, $sdate, $edate);
+ if ( $cust_bill_pkg->pkgnum ) {
+
+ ($pkg, $setup, $recur, $sdate, $edate) = (
+ $cust_bill_pkg->cust_pkg->part_pkg->pkg,
+ ( $cust_bill_pkg->setup != 0
+ ? sprintf("%.2f", $cust_bill_pkg->setup )
+ : '' ),
+ ( $cust_bill_pkg->recur != 0
+ ? sprintf("%.2f", $cust_bill_pkg->recur )
+ : '' ),
+ time2str("%x", $cust_bill_pkg->sdate),
+ time2str("%x", $cust_bill_pkg->edate),
+ );
- $csv->combine(
- '', # 1 | N/A-Leave Empty CHAR 2
- '', # 2 | N/A-Leave Empty CHAR 15
- $opt{'tracctnum'}, # 3 | Transaction Account No CHAR 15
- $self->invnum, # 4 | Transaction Invoice No CHAR 15
- $cust_main->zip, # 5 | Transaction Zip Code CHAR 5
- $cust_main->company, # 6 | Transaction Company Bill To CHAR 30
- #$cust_main->payname, # 7 | Transaction Contact Bill To CHAR 30
- $cust_main->contact, # 7 | Transaction Contact Bill To CHAR 30
- $cust_main->address2, # 8 | Additional Address Unit Info CHAR 30
- $cust_main->address1, # 9 | Bill To Street Address CHAR 30
- '', # 10 | Ancillary Billing Information CHAR 30
- $cust_main->city, # 11 | Transaction City Bill To CHAR 20
- $cust_main->state, # 12 | Transaction State Bill To CHAR 2
-
- # XXX ?
- time2str("%m/%d/%Y", $self->_date), # 13 | Bill Cycle Close Date CHAR 10
-
- # XXX ?
- $duedate, # 14 | Bill Due Date CHAR 10
-
- $previous_balance, # 15 | Previous Balance NUM* 9
- $pmt_cr_applied, # 16 | Pmt/CR Applied NUM* 9
- sprintf("%.2f", $self->charged), # 17 | Total Current Charges NUM* 9
- $totaldue, # 18 | Total Amt Due NUM* 9
- $totaldue, # 19 | Total Amt Due NUM* 9
- '', # 20 | 30 Day Aging NUM* 9
- '', # 21 | 60 Day Aging NUM* 9
- '', # 22 | 90 Day Aging NUM* 9
- 'N', # 23 | Y/N CHAR 1
- '', # 24 | Remittance automation CHAR 100
- $taxtotal, # 25 | Total Taxes & Fees NUM* 9
- $self->custnum, # 26 | Customer Reference Number CHAR 15
- '0', # 27 | Federal Tax*** NUM* 9
- sprintf("%.2f", $taxtotal), # 28 | State Tax*** NUM* 9
- '0', # 29 | Other Taxes & Fees*** NUM* 9
- );
+ } else { #pkgnum tax
+ next unless $cust_bill_pkg->setup != 0;
+ my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc')
+ ? ( $cust_bill_pkg->itemdesc || 'Tax' )
+ : 'Tax';
+ ($pkg, $setup, $recur, $sdate, $edate) =
+ ( $itemdesc, sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' );
+ }
- } else {
-
$csv->combine(
- 'cust_bill',
+ 'cust_bill_pkg',
$self->invnum,
- $self->custnum,
- time2str("%x", $self->_date),
- sprintf("%.2f", $self->charged),
- ( map { $cust_main->getfield($_) }
- qw( first last company address1 address2 city state zip country ) ),
- map { '' } (1..5),
+ ( map { '' } (1..11) ),
+ ($pkg, $setup, $recur, $sdate, $edate)
) or die "can't create csv";
- }
+ print CSV $csv->string. "\n";
- my $header = $csv->string. "\n";
-
- my $detail = '';
- if ( lc($opt{'format'}) eq 'billco' ) {
-
- my $lineseq = 0;
- foreach my $item ( $self->_items_pkg ) {
-
- $csv->combine(
- '', # 1 | N/A-Leave Empty CHAR 2
- '', # 2 | N/A-Leave Empty CHAR 15
- $opt{'tracctnum'}, # 3 | Account Number CHAR 15
- $self->invnum, # 4 | Invoice Number CHAR 15
- $lineseq++, # 5 | Line Sequence (sort order) NUM 6
- $item->{'description'}, # 6 | Transaction Detail CHAR 100
- $item->{'amount'}, # 7 | Amount NUM* 9
- '', # 8 | Line Format Control** CHAR 2
- '', # 9 | Grouping Code CHAR 2
- '', # 10 | User Defined CHAR 15
- );
+ }
- $detail .= $csv->string. "\n";
+ close CSV or die "can't close CSV: $!";
- }
+ #part two: upload it
+ my $net;
+ if ( $opt{protocol} eq 'ftp' ) {
+ eval "use Net::FTP;";
+ die $@ if $@;
+ $net = Net::FTP->new($opt{server}) or die @$;
} else {
+ die "unknown protocol: $opt{protocol}";
+ }
- foreach my $cust_bill_pkg ( $self->cust_bill_pkg ) {
-
- my($pkg, $setup, $recur, $sdate, $edate);
- if ( $cust_bill_pkg->pkgnum ) {
-
- ($pkg, $setup, $recur, $sdate, $edate) = (
- $cust_bill_pkg->cust_pkg->part_pkg->pkg,
- ( $cust_bill_pkg->setup != 0
- ? sprintf("%.2f", $cust_bill_pkg->setup )
- : '' ),
- ( $cust_bill_pkg->recur != 0
- ? sprintf("%.2f", $cust_bill_pkg->recur )
- : '' ),
- ( $cust_bill_pkg->sdate
- ? time2str("%x", $cust_bill_pkg->sdate)
- : '' ),
- ($cust_bill_pkg->edate
- ?time2str("%x", $cust_bill_pkg->edate)
- : '' ),
- );
-
- } else { #pkgnum tax
- next unless $cust_bill_pkg->setup != 0;
- my $itemdesc = defined $cust_bill_pkg->dbdef_table->column('itemdesc')
- ? ( $cust_bill_pkg->itemdesc || 'Tax' )
- : 'Tax';
- ($pkg, $setup, $recur, $sdate, $edate) =
- ( $itemdesc, sprintf("%10.2f",$cust_bill_pkg->setup), '', '', '' );
- }
-
- $csv->combine(
- 'cust_bill_pkg',
- $self->invnum,
- ( map { '' } (1..11) ),
- ($pkg, $setup, $recur, $sdate, $edate)
- ) or die "can't create csv";
+ $net->login( $opt{username}, $opt{password} )
+ or die "can't FTP to $opt{username}\@$opt{server}: login error: $@";
- $detail .= $csv->string. "\n";
+ $net->binary or die "can't set binary mode";
- }
+ $net->cwd($opt{dir}) or die "can't cwd to $opt{dir}";
- }
+ $net->put($file) or die "can't put $file: $!";
- ( $header, $detail );
+ $net->quit;
+
+ unlink $file;
}
@@ -1275,7 +681,7 @@ sub batch_card {
'state' => $cust_main->getfield('state'),
'zip' => $cust_main->getfield('zip'),
'country' => $cust_main->getfield('country'),
- 'cardnum' => $cust_main->payinfo,
+ 'cardnum' => $cust_main->getfield('payinfo'),
'exp' => $cust_main->getfield('paydate'),
'payname' => $cust_main->getfield('payname'),
'amount' => $self->owed,
@@ -1305,9 +711,7 @@ sub _agent_plandata {
'plan' => 'send_agent',
'plandata' => { 'op' => '~',
'value' => "(^|\n)agentnum ".
- '([0-9]*, )*'.
$self->cust_main->agentnum.
- '(, [0-9]*)*'.
"(\n|\$)",
},
},
@@ -1338,7 +742,7 @@ L<Time::Local> and L<Date::Parse> for conversion functions.
=cut
-#still some false laziness w/_items stuff (and send_csv)
+#still some false laziness w/print_text
sub print_text {
my( $self, $today, $template ) = @_;
@@ -1379,49 +783,50 @@ sub print_text {
( grep { ! $_->pkgnum } $self->cust_bill_pkg ), #then taxes
) {
- my $desc = $cust_bill_pkg->desc;
+ if ( $cust_bill_pkg->pkgnum ) {
- if ( $cust_bill_pkg->pkgnum > 0 ) {
+ 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;
if ( $cust_bill_pkg->setup != 0 ) {
- my $description = $desc;
+ 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_bill_pkg->cust_pkg->h_labels($self->_date);
+ $cust_pkg->h_labels($self->_date);
}
if ( $cust_bill_pkg->recur != 0 ) {
push @buf, [
- "$desc (" . time2str("%x", $cust_bill_pkg->sdate) . " - " .
- time2str("%x", $cust_bill_pkg->edate) . ")",
+ "$pkg (" . time2str("%x", $cust_bill_pkg->sdate) . " - " .
+ time2str("%x", $cust_bill_pkg->edate) . ")",
$money_char. sprintf("%10.2f", $cust_bill_pkg->recur)
];
push @buf,
map { [ " ". $_->[0]. ": ". $_->[1], '' ] }
- $cust_bill_pkg->cust_pkg->h_labels( $cust_bill_pkg->edate,
- $cust_bill_pkg->sdate );
+ $cust_pkg->h_labels($cust_bill_pkg->edate, $cust_bill_pkg->sdate);
}
push @buf, map { [ " $_", '' ] } $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 @buf, [ $desc,
+ push @buf, [ $itemdesc,
$money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ];
}
if ( $cust_bill_pkg->recur != 0 ) {
- push @buf, [ "$desc (". time2str("%x", $cust_bill_pkg->sdate). " - "
- . time2str("%x", $cust_bill_pkg->edate). ")",
+ push @buf, [ "$itemdesc (". time2str("%x", $cust_bill_pkg->sdate). " - "
+ . time2str("%x", $cust_bill_pkg->edate). ")",
$money_char. sprintf("%10.2f", $cust_bill_pkg->recur)
];
}
-
}
-
}
push @buf,['','-----------'];
@@ -1530,10 +935,8 @@ sub print_text {
if $cust_main->address2;
$FS::cust_bill::_template::address[$l++] =
$cust_main->city. ", ". $cust_main->state. " ". $cust_main->zip;
-
- my $countrydefault = $conf->config('countrydefault') || 'US';
- $FS::cust_bill::_template::address[$l++] = code2country($cust_main->country)
- unless $cust_main->country eq $countrydefault;
+ $FS::cust_bill::_template::address[$l++] = $cust_main->country
+ unless $cust_main->country eq 'US';
# #overdue? (variable for the template)
# $FS::cust_bill::_template::overdue = (
@@ -1581,14 +984,13 @@ L<Time::Local> and L<Date::Parse> for conversion functions.
=cut
-#still some false laziness w/print_text and print_html (and send_csv) (mostly print_text should use _items stuff though)
+#still some false laziness w/print_text
sub print_latex {
my( $self, $today, $template ) = @_;
$today ||= time;
- warn "FS::cust_bill::print_latex called on $self with suffix $template\n"
- if $DEBUG;
+# 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 !~ /^(CHEK|DCHK)$/;
@@ -1598,45 +1000,21 @@ sub print_latex {
#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
$template ||= $self->_agent_template;
my $templatefile = 'invoice_latex';
my $suffix = length($template) ? "_$template" : '';
$templatefile .= $suffix;
- my @invoice_template = map "$_\n", $conf->config($templatefile)
+ my @invoice_template = $conf->config($templatefile)
or die "cannot load config file $templatefile";
- my($format, $text_template);
- if ( grep { /^%%Detail/ } @invoice_template ) {
- #change this to a die when the old code is removed
- warn "old-style invoice template $templatefile; ".
- "patch with conf/invoice_latex.diff or use new conf/invoice_latex*\n";
- $format = 'old';
- } else {
- $format = 'Text::Template';
- $text_template = new Text::Template(
- TYPE => 'ARRAY',
- SOURCE => \@invoice_template,
- DELIMITERS => [ '[@--', '--@]' ],
- );
-
- $text_template->compile()
- or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR;
- }
-
- my $returnaddress;
- if ( length($conf->config_orbase('invoice_latexreturnaddress', $template)) ) {
- $returnaddress = join("\n",
- $conf->config_orbase('invoice_latexreturnaddress', $template)
- );
- } else {
- $returnaddress = '~';
- }
-
my %invoice_data = (
'invnum' => $self->invnum,
'date' => time2str('%b %o, %Y', $self->_date),
- 'today' => time2str('%b %o, %Y', $today),
'agent' => _latex_escape($cust_main->agent->agent),
'payname' => _latex_escape($cust_main->payname),
'company' => _latex_escape($cust_main->company),
@@ -1645,30 +1023,23 @@ sub print_latex {
'city' => _latex_escape($cust_main->city),
'state' => _latex_escape($cust_main->state),
'zip' => _latex_escape($cust_main->zip),
- 'footer' => join("\n", $conf->config_orbase('invoice_latexfooter', $template) ),
- 'smallfooter' => join("\n", $conf->config_orbase('invoice_latexsmallfooter', $template) ),
- 'returnaddress' => $returnaddress,
+ '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') ),
- 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
);
my $countrydefault = $conf->config('countrydefault') || 'US';
- if ( $cust_main->country eq $countrydefault ) {
- $invoice_data{'country'} = '';
- } else {
- $invoice_data{'country'} = _latex_escape(code2country($cust_main->country));
- }
+ $invoice_data{'country'} = '' if $invoice_data{'country'} eq $countrydefault;
+ #do variable substitutions in notes
$invoice_data{'notes'} =
join("\n",
-# #do variable substitutions in notes
-# map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
- $conf->config_orbase('invoice_latexnotes', $template)
+ map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
+ $conf->config_orbase('invoice_latexnotes', $suffix)
);
- warn "invoice notes: ". $invoice_data{'notes'}. "\n"
- if $DEBUG;
$invoice_data{'footer'} =~ s/\n+$//;
$invoice_data{'smallfooter'} =~ s/\n+$//;
@@ -1679,200 +1050,110 @@ sub print_latex {
? _latex_escape("Purchase Order #". $cust_main->payinfo)
: '~';
+ my @line_item = ();
+ my @total_item = ();
my @filled_in = ();
- if ( $format eq 'old' ) {
-
- my @line_item = ();
- my @total_item = ();
- 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 += $tax->{'amount'};
- $invoice_data{'total_amount'} = '\dollar '. $tax->{'amount'};
- push @total_fill,
- map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
- @total_item;
- }
+ while ( @invoice_template ) {
+ my $line = shift @invoice_template;
- 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;
+ 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{'total_item'} = '\textbf{Total}';
- $invoice_data{'total_amount'} =
- '\textbf{\dollar '. sprintf('%.2f', $self->charged + $pr_total ). '}';
+ $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;
-
- #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. '}';
+ }
+
+ if ( $taxtotal ) {
+ $invoice_data{'total_item'} = 'Sub-total';
$invoice_data{'total_amount'} =
- '\textbf{\dollar '. sprintf('%.2f', $self->owed + $pr_total ). '}';
- push @total_fill,
+ '\dollar '. sprintf('%.2f', $self->charged - $taxtotal );
+ unshift @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;
- }
+ $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;
+ }
- } elsif ( $format eq 'Text::Template' ) {
-
- my @detail_items = ();
- my @total_items = ();
-
- $invoice_data{'detail_items'} = \@detail_items;
- $invoice_data{'total_items'} = \@total_items;
-
- foreach my $line_item ( $self->_items ) {
- my $detail = {
- ext_description => [],
- };
- $detail->{'ref'} = $line_item->{'pkgnum'};
- $detail->{'quantity'} = 1;
- $detail->{'description'} = _latex_escape($line_item->{'description'});
- if ( exists $line_item->{'ext_description'} ) {
- @{$detail->{'ext_description'}} = map {
- _latex_escape($_);
- } @{$line_item->{'ext_description'}};
+ # 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;
}
- $detail->{'amount'} = $line_item->{'amount'};
- $detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A';
-
- push @detail_items, $detail;
- }
-
-
- my $taxtotal = 0;
- foreach my $tax ( $self->_items_tax ) {
- my $total = {};
- $total->{'total_item'} = _latex_escape($tax->{'description'});
- $taxtotal += $tax->{'amount'};
- $total->{'total_amount'} = '\dollar '. $tax->{'amount'};
- push @total_items, $total;
- }
-
- if ( $taxtotal ) {
- my $total = {};
- $total->{'total_item'} = 'Sub-total';
- $total->{'total_amount'} =
- '\dollar '. sprintf('%.2f', $self->charged - $taxtotal );
- unshift @total_items, $total;
- }
-
- {
- my $total = {};
- $total->{'total_item'} = '\textbf{Total}';
- $total->{'total_amount'} =
- '\textbf{\dollar '. sprintf('%.2f', $self->charged + $pr_total ). '}';
- push @total_items, $total;
- }
-
- #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments
-
- # credits
- foreach my $credit ( $self->_items_credits ) {
- my $total;
- $total->{'total_item'} = _latex_escape($credit->{'description'});
- #$credittotal
- $total->{'total_amount'} = '-\dollar '. $credit->{'amount'};
- push @total_items, $total;
- }
-
- # payments
- foreach my $payment ( $self->_items_payments ) {
- my $total = {};
- $total->{'total_item'} = _latex_escape($payment->{'description'});
- #$paymenttotal
- $total->{'total_amount'} = '-\dollar '. $payment->{'amount'};
- push @total_items, $total;
- }
-
- {
- my $total;
- $total->{'total_item'} = '\textbf{'. $self->balance_due_msg. '}';
- $total->{'total_amount'} =
+
+ $invoice_data{'total_item'} = '\textbf{'. $self->balance_due_msg. '}';
+ $invoice_data{'total_amount'} =
'\textbf{\dollar '. sprintf('%.2f', $self->owed + $pr_total ). '}';
- push @total_items, $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;
}
- } else {
- die "guru meditation #54";
+ }
+
+ sub nounder {
+ my $var = $1;
+ $var =~ s/_/\-/g;
+ $var;
}
my $dir = $FS::UID::conf_dir. "cache.". $FS::UID::datasrc;
@@ -1881,13 +1162,7 @@ sub print_latex {
SUFFIX => '.tex',
UNLINK => 0,
) or die "can't open temp file: $!\n";
- if ( $format eq 'old' ) {
- print $fh join('', @filled_in );
- } elsif ( $format eq 'Text::Template' ) {
- $text_template->fill_in(OUTPUT => $fh, HASH => \%invoice_data);
- } else {
- die "guru meditation #32";
- }
+ print $fh join("\n", @filled_in ), "\n";
close $fh;
$fh->filename =~ /^(.*).tex$/ or die "unparsable filename: ". $fh->filename;
@@ -1917,12 +1192,12 @@ sub print_ps {
my $sfile = shell_quote $file;
system("pslatex $sfile.tex >/dev/null 2>&1") == 0
- or die "pslatex $file.tex failed; see $file.log for details?\n";
+ or die "pslatex $file.tex failed: $!";
system("pslatex $sfile.tex >/dev/null 2>&1") == 0
- or die "pslatex $file.tex failed; see $file.log for details?\n";
+ or die "pslatex $file.tex failed: $!";
system('dvips', '-q', '-t', 'letter', "$file.dvi", '-o', "$file.ps" ) == 0
- or die "dvips failed";
+ or die "dvips failed: $!";
open(POSTSCRIPT, "<$file.ps")
or die "can't open $file.ps: $! (error in LaTeX template?)\n";
@@ -1966,9 +1241,9 @@ sub print_pdf {
my $sfile = shell_quote $file;
system("pslatex $sfile.tex >/dev/null 2>&1") == 0
- or die "pslatex $file.tex failed; see $file.log for details?\n";
+ or die "pslatex $file.tex failed: $!";
system("pslatex $sfile.tex >/dev/null 2>&1") == 0
- or die "pslatex $file.tex failed; see $file.log for details?\n";
+ or die "pslatex $file.tex failed: $!";
#system('dvipdf', "$file.dvi", "$file.pdf" );
system(
@@ -1994,215 +1269,6 @@ sub print_pdf {
}
-=item print_html [ TIME [ , TEMPLATE [ , CID ] ] ]
-
-Returns an HTML 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.
-
-CID is a MIME Content-ID used to create a "cid:" URL for the logo image, used
-when emailing the invoice as part of a multipart/related MIME email.
-
-=cut
-
-#some falze laziness w/print_text and print_latex (and send_csv)
-sub print_html {
- my( $self, $today, $template, $cid ) = @_;
- $today ||= time;
-
- my $cust_main = $self->cust_main;
- $cust_main->payname( $cust_main->first. ' '. $cust_main->getfield('last') )
- unless $cust_main->payname && $cust_main->payby !~ /^(CHEK|DCHK)$/;
-
- $template ||= $self->_agent_template;
- my $templatefile = 'invoice_html';
- my $suffix = length($template) ? "_$template" : '';
- $templatefile .= $suffix;
- my @html_template = map "$_\n", $conf->config($templatefile)
- or die "cannot load config file $templatefile";
-
- my $html_template = new Text::Template(
- TYPE => 'ARRAY',
- SOURCE => \@html_template,
- DELIMITERS => [ '<%=', '%>' ],
- );
-
- $html_template->compile()
- or die 'While compiling ' . $templatefile . ': ' . $Text::Template::ERROR;
-
- my %invoice_data = (
- 'invnum' => $self->invnum,
- 'date' => time2str('%b&nbsp;%o,&nbsp;%Y', $self->_date),
- 'today' => time2str('%b %o, %Y', $today),
- 'agent' => encode_entities($cust_main->agent->agent),
- 'payname' => encode_entities($cust_main->payname),
- 'company' => encode_entities($cust_main->company),
- 'address1' => encode_entities($cust_main->address1),
- 'address2' => encode_entities($cust_main->address2),
- 'city' => encode_entities($cust_main->city),
- 'state' => encode_entities($cust_main->state),
- 'zip' => encode_entities($cust_main->zip),
- 'terms' => $conf->config('invoice_default_terms')
- || 'Payable upon receipt',
- 'cid' => $cid,
- 'template' => $template,
-# 'conf_dir' => "$FS::UID::conf_dir/conf.$FS::UID::datasrc",
- );
-
- if (
- defined( $conf->config_orbase('invoice_htmlreturnaddress', $template) )
- && length( $conf->config_orbase('invoice_htmlreturnaddress', $template) )
- ) {
- $invoice_data{'returnaddress'} =
- join("\n", $conf->config('invoice_htmlreturnaddress', $template) );
- } else {
- $invoice_data{'returnaddress'} =
- join("\n", map {
- s/~/&nbsp;/g;
- s/\\\\\*?\s*$/<BR>/;
- s/\\hyphenation\{[\w\s\-]+\}//;
- $_;
- }
- $conf->config_orbase( 'invoice_latexreturnaddress',
- $template
- )
- );
- }
-
- my $countrydefault = $conf->config('countrydefault') || 'US';
- if ( $cust_main->country eq $countrydefault ) {
- $invoice_data{'country'} = '';
- } else {
- $invoice_data{'country'} =
- encode_entities(code2country($cust_main->country));
- }
-
- if (
- defined( $conf->config_orbase('invoice_htmlnotes', $template) )
- && length( $conf->config_orbase('invoice_htmlnotes', $template) )
- ) {
- $invoice_data{'notes'} =
- join("\n", $conf->config_orbase('invoice_htmlnotes', $template) );
- } else {
- $invoice_data{'notes'} =
- join("\n", map {
- s/%%(.*)$/<!-- $1 -->/;
- s/\\section\*\{\\textsc\{(.)(.*)\}\}/<p><b><font size="+1">$1<\/font>\U$2<\/b>/;
- s/\\begin\{enumerate\}/<ol>/;
- s/\\item / <li>/;
- s/\\end\{enumerate\}/<\/ol>/;
- s/\\textbf\{(.*)\}/<b>$1<\/b>/;
- $_;
- }
- $conf->config_orbase('invoice_latexnotes', $template)
- );
- }
-
-# #do variable substitutions in notes
-# $invoice_data{'notes'} =
-# join("\n",
-# map { my $b=$_; $b =~ s/\$(\w+)/$invoice_data{$1}/eg; $b }
-# $conf->config_orbase('invoice_latexnotes', $suffix)
-# );
-
- if (
- defined( $conf->config_orbase('invoice_htmlfooter', $template) )
- && length( $conf->config_orbase('invoice_htmlfooter', $template) )
- ) {
- $invoice_data{'footer'} =
- join("\n", $conf->config_orbase('invoice_htmlfooter', $template) );
- } else {
- $invoice_data{'footer'} =
- join("\n", map { s/~/&nbsp;/g; s/\\\\\*?\s*$/<BR>/; $_; }
- $conf->config_orbase('invoice_latexfooter', $template)
- );
- }
-
- $invoice_data{'po_line'} =
- ( $cust_main->payby eq 'BILL' && $cust_main->payinfo )
- ? encode_entities("Purchase Order #". $cust_main->payinfo)
- : '';
-
- my $money_char = $conf->config('money_char') || '$';
-
- foreach my $line_item ( $self->_items ) {
- my $detail = {
- ext_description => [],
- };
- $detail->{'ref'} = $line_item->{'pkgnum'};
- $detail->{'description'} = encode_entities($line_item->{'description'});
- if ( exists $line_item->{'ext_description'} ) {
- @{$detail->{'ext_description'}} = map {
- encode_entities($_);
- } @{$line_item->{'ext_description'}};
- }
- $detail->{'amount'} = $money_char. $line_item->{'amount'};
- $detail->{'product_code'} = $line_item->{'pkgpart'} || 'N/A';
-
- push @{$invoice_data{'detail_items'}}, $detail;
- }
-
-
- my $taxtotal = 0;
- foreach my $tax ( $self->_items_tax ) {
- my $total = {};
- $total->{'total_item'} = encode_entities($tax->{'description'});
- $taxtotal += $tax->{'amount'};
- $total->{'total_amount'} = $money_char. $tax->{'amount'};
- push @{$invoice_data{'total_items'}}, $total;
- }
-
- if ( $taxtotal ) {
- my $total = {};
- $total->{'total_item'} = 'Sub-total';
- $total->{'total_amount'} =
- $money_char. sprintf('%.2f', $self->charged - $taxtotal );
- unshift @{$invoice_data{'total_items'}}, $total;
- }
-
- my( $pr_total, @pr_cust_bill ) = $self->previous; #previous balance
- {
- my $total = {};
- $total->{'total_item'} = '<b>Total</b>';
- $total->{'total_amount'} =
- "<b>$money_char". sprintf('%.2f', $self->charged + $pr_total ). '</b>';
- push @{$invoice_data{'total_items'}}, $total;
- }
-
- #foreach my $thing ( sort { $a->_date <=> $b->_date } $self->_items_credits, $self->_items_payments
-
- # credits
- foreach my $credit ( $self->_items_credits ) {
- my $total;
- $total->{'total_item'} = encode_entities($credit->{'description'});
- #$credittotal
- $total->{'total_amount'} = "-$money_char". $credit->{'amount'};
- push @{$invoice_data{'total_items'}}, $total;
- }
-
- # payments
- foreach my $payment ( $self->_items_payments ) {
- my $total = {};
- $total->{'total_item'} = encode_entities($payment->{'description'});
- #$paymenttotal
- $total->{'total_amount'} = "-$money_char". $payment->{'amount'};
- push @{$invoice_data{'total_items'}}, $total;
- }
-
- {
- my $total;
- $total->{'total_item'} = '<b>'. $self->balance_due_msg. '</b>';
- $total->{'total_amount'} =
- "<b>$money_char". sprintf('%.2f', $self->owed + $pr_total ). '</b>';
- push @{$invoice_data{'total_items'}}, $total;
- }
-
- $html_template->fill_in( HASH => \%invoice_data);
-}
-
# quick subroutine for print_latex
#
# There are ten characters that LaTeX treats as special characters, which
@@ -2215,7 +1281,6 @@ sub print_html {
sub _latex_escape {
my $value = shift;
$value =~ s/([#\$%&~_\^{}])( )?/"\\$1". ( ( defined($2) && length($2) ) ? "\\$2" : '' )/ge;
- $value =~ s/([<>])/\$$1\$/g;
$value;
}
@@ -2258,7 +1323,7 @@ sub _items_previous {
' ('. time2str('%x',$_->_date). ')',
#'pkgpart' => 'N/A',
'pkgnum' => 'N/A',
- 'amount' => sprintf("%.2f", $_->owed),
+ 'amount' => sprintf("%10.2f", $_->owed),
};
}
@b;
@@ -2296,54 +1361,58 @@ sub _items_cust_bill_pkg {
my @b = ();
foreach my $cust_bill_pkg ( @$cust_bill_pkg ) {
- my $desc = $cust_bill_pkg->desc;
+ if ( $cust_bill_pkg->pkgnum ) {
- if ( $cust_bill_pkg->pkgnum > 0 ) {
+ 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;
if ( $cust_bill_pkg->setup != 0 ) {
- my $description = $desc;
+ my $description = $pkg;
$description .= ' Setup' if $cust_bill_pkg->recur != 0;
- my @d = $cust_bill_pkg->cust_pkg->h_labels_short($self->_date);
+ my @d = $cust_pkg->h_labels_short($self->_date);
push @d, $cust_bill_pkg->details if $cust_bill_pkg->recur == 0;
push @b, {
description => $description,
#pkgpart => $part_pkg->pkgpart,
- pkgnum => $cust_bill_pkg->pkgnum,
- amount => sprintf("%.2f", $cust_bill_pkg->setup),
+ pkgnum => $cust_pkg->pkgnum,
+ amount => sprintf("%10.2f", $cust_bill_pkg->setup),
ext_description => \@d,
};
}
if ( $cust_bill_pkg->recur != 0 ) {
push @b, {
- description => "$desc (" .
+ description => "$pkg (" .
time2str('%x', $cust_bill_pkg->sdate). ' - '.
time2str('%x', $cust_bill_pkg->edate). ')',
#pkgpart => $part_pkg->pkgpart,
- pkgnum => $cust_bill_pkg->pkgnum,
- amount => sprintf("%.2f", $cust_bill_pkg->recur),
- ext_description =>
- [ $cust_bill_pkg->cust_pkg->h_labels_short( $cust_bill_pkg->edate,
- $cust_bill_pkg->sdate),
- $cust_bill_pkg->details,
- ],
+ pkgnum => $cust_pkg->pkgnum,
+ amount => sprintf("%10.2f", $cust_bill_pkg->recur),
+ ext_description => [ $cust_pkg->h_labels_short($cust_bill_pkg->edate,
+ $cust_bill_pkg->sdate),
+ $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' => $desc,
- 'amount' => sprintf("%.2f", $cust_bill_pkg->setup),
+ 'description' => $itemdesc,
+ 'amount' => sprintf("%10.2f", $cust_bill_pkg->setup),
};
}
if ( $cust_bill_pkg->recur != 0 ) {
push @b, {
- 'description' => "$desc (".
+ 'description' => "$itemdesc (".
time2str("%x", $cust_bill_pkg->sdate). ' - '.
time2str("%x", $cust_bill_pkg->edate). ')',
- 'amount' => sprintf("%.2f", $cust_bill_pkg->recur),
+ 'amount' => sprintf("%10.2f", $cust_bill_pkg->recur),
};
}
@@ -2374,7 +1443,7 @@ sub _items_credits {
# $reason,
'description' => 'Credit applied '.
time2str("%x",$_->cust_credit->_date). $reason,
- 'amount' => sprintf("%.2f",$_->amount),
+ 'amount' => sprintf("%10.2f",$_->amount),
};
}
#foreach ( @cr_cust_credit ) {
@@ -2400,7 +1469,7 @@ sub _items_payments {
push @b, {
'description' => "Payment received ".
time2str("%x",$_->cust_pay->_date ),
- 'amount' => sprintf("%.2f", $_->amount )
+ 'amount' => sprintf("%10.2f", $_->amount )
};
}
@@ -2408,123 +1477,6 @@ sub _items_payments {
}
-
-=back
-
-=head1 SUBROUTINES
-
-=over 4
-
-=item reprint
-
-=cut
-
-sub process_reprint {
- process_re_X('print', @_);
-}
-
-=item reemail
-
-=cut
-
-sub process_reemail {
- process_re_X('email', @_);
-}
-
-=item refax
-
-=cut
-
-sub process_refax {
- process_re_X('fax', @_);
-}
-
-use Storable qw(thaw);
-use Data::Dumper;
-use MIME::Base64;
-sub process_re_X {
- my( $method, $job ) = ( shift, shift );
-
- my $param = thaw(decode_base64(shift));
- warn Dumper($param) if $DEBUG;
-
- re_X(
- $method,
- $job,
- %$param,
- );
-
-}
-
-sub re_X {
- my($method, $job, %param ) = @_;
-# [ 'begin', 'end', 'agentnum', 'open', 'days', 'newest_percust' ],
-
- #some false laziness w/search/cust_bill.html
- my $distinct = '';
- my $orderby = 'ORDER BY cust_bill._date';
-
- my @where;
-
- if ( $param{'begin'} =~ /^(\d+)$/ ) {
- push @where, "cust_bill._date >= $1";
- }
- if ( $param{'end'} =~ /^(\d+)$/ ) {
- push @where, "cust_bill._date < $1";
- }
- if ( $param{'agentnum'} =~ /^(\d+)$/ ) {
- push @where, "cust_main.agentnum = $1";
- }
-
- my $owed =
- "charged - ( SELECT COALESCE(SUM(amount),0) FROM cust_bill_pay
- WHERE cust_bill_pay.invnum = cust_bill.invnum )
- - ( SELECT COALESCE(SUM(amount),0) FROM cust_credit_bill
- WHERE cust_credit_bill.invnum = cust_bill.invnum )";
-
- push @where, "0 != $owed"
- if $param{'open'};
-
- push @where, "cust_bill._date < ". (time-86400*$param{'days'})
- if $param{'days'};
-
- my $extra_sql = scalar(@where) ? 'WHERE '. join(' AND ', @where) : '';
-
- my $addl_from = 'left join cust_main using ( custnum )';
-
- if ( $param{'newest_percust'} ) {
- $distinct = 'DISTINCT ON ( cust_bill.custnum )';
- $orderby = 'ORDER BY cust_bill.custnum ASC, cust_bill._date DESC';
- #$count_query = "SELECT COUNT(DISTINCT cust_bill.custnum), 'N/A', 'N/A'";
- }
-
- my @cust_bill = qsearch( 'cust_bill',
- {},
- "$distinct cust_bill.*",
- $extra_sql,
- '',
- $addl_from
- );
-
- my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
- foreach my $cust_bill ( @cust_bill ) {
- $cust_bill->$method();
-
- if ( $job ) { #progressbar foo
- $num++;
- if ( time - $min_sec > $last ) {
- my $error = $job->update_statustext(
- int( 100 * $num / scalar(@cust_bill) )
- );
- die $error if $error;
- $last = time;
- }
- }
-
- }
-
-}
-
=back
=head1 BUGS
diff --git a/FS/FS/cust_bill_event.pm b/FS/FS/cust_bill_event.pm
index 128e5a53d..ddd676281 100644
--- a/FS/FS/cust_bill_event.pm
+++ b/FS/FS/cust_bill_event.pm
@@ -1,15 +1,12 @@
package FS::cust_bill_event;
use strict;
-use vars qw( @ISA $DEBUG );
+use vars qw( @ISA );
use FS::Record qw( qsearch qsearchs );
-use FS::cust_main_Mixin;
use FS::cust_bill;
use FS::part_bill_event;
-@ISA = qw(FS::cust_main_Mixin FS::Record);
-
-$DEBUG = 0;
+@ISA = qw(FS::Record);
=head1 NAME
@@ -71,13 +68,6 @@ points to. You can ask the object for a copy with the I<hash> method.
sub table { 'cust_bill_event'; }
-sub cust_linked { $_[0]->cust_main_custnum; }
-sub cust_unlinked_msg {
- my $self = shift;
- "WARNING: can't find cust_main.custnum ". $self->custnum.
- ' (cust_bill.invnum '. $self->invnum. ')';
-}
-
=item insert
Adds this record to the database. If there is an error, returns the error,
@@ -175,98 +165,6 @@ sub retry {
=back
-=head1 SUBROUTINES
-
-=over 4
-
-=item reprint
-
-=cut
-
-sub process_reprint {
- process_re_X('print', @_);
-}
-
-=item reemail
-
-=cut
-
-sub process_reemail {
- process_re_X('email', @_);
-}
-
-=item refax
-
-=cut
-
-sub process_refax {
- process_re_X('fax', @_);
-}
-
-use Storable qw(thaw);
-use Data::Dumper;
-use MIME::Base64;
-sub process_re_X {
- my( $method, $job ) = ( shift, shift );
-
- my $param = thaw(decode_base64(shift));
- warn Dumper($param) if $DEBUG;
-
- re_X(
- $method,
- $param->{'beginning'},
- $param->{'ending'},
- $param->{'failed'},
- $job,
- );
-
-}
-
-sub re_X {
- my($method, $beginning, $ending, $failed, $job) = @_;
-
- my $where = " WHERE plan LIKE 'send%'".
- " AND cust_bill_event._date >= $beginning".
- " AND cust_bill_event._date <= $ending";
- $where .= " AND statustext != '' AND statustext IS NOT NULL"
- if $failed;
-
- my $from = 'LEFT JOIN part_bill_event USING ( eventpart )';
-
- my @cust_bill_event = qsearch( 'cust_bill_event', {}, '', $where, '', $from );
-
- my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
- foreach my $cust_bill_event ( @cust_bill_event ) {
-
- $cust_bill_event->cust_bill->$method(
- $cust_bill_event->part_bill_event->templatename
- );
-
- if ( $job ) { #progressbar foo
- $num++;
- if ( time - $min_sec > $last ) {
- my $error = $job->update_statustext(
- int( 100 * $num / scalar(@cust_bill_event) )
- );
- die $error if $error;
- $last = time;
- }
- }
-
- }
-
- #this doesn't work, but it would be nice
- #if ( $job ) { #progressbar foo
- # my $error = $job->update_statustext(
- # scalar(@cust_bill_event). " invoices re-${method}ed"
- # );
- # die $error if $error;
- #}
-
-}
-
-=back
-
=head1 BUGS
Far too early in the morning.
diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm
index d718b05fd..6800707fe 100644
--- a/FS/FS/cust_bill_pkg.pm
+++ b/FS/FS/cust_bill_pkg.pm
@@ -3,12 +3,11 @@ package FS::cust_bill_pkg;
use strict;
use vars qw( @ISA );
use FS::Record qw( qsearch qsearchs dbdef dbh );
-use FS::cust_main_Mixin;
use FS::cust_pkg;
use FS::cust_bill;
use FS::cust_bill_pkg_detail;
-@ISA = qw( FS::cust_main_Mixin FS::Record );
+@ISA = qw( FS::Record );
=head1 NAME
@@ -37,11 +36,9 @@ supported:
=over 4
-=item billpkgnum - primary key
-
=item invnum - invoice (see L<FS::cust_bill>)
-=item pkgnum - package (see L<FS::cust_pkg>) or 0 for the special virtual sales tax package, or -1 for the virtual line item (itemdesc is used for the line)
+=item pkgnum - package (see L<FS::cust_pkg>) or 0 for the special virtual sales tax package
=item setup - setup fee
@@ -51,7 +48,7 @@ supported:
=item edate - ending date of recurring fee
-=item itemdesc - Line item description (currentlty used only when pkgnum is 0 or -1)
+=item itemdesc - Line item description (currentlty used only when pkgnum is 0)
=back
@@ -156,8 +153,7 @@ sub check {
my $self = shift;
my $error =
- $self->ut_numbern('billpkgnum')
- || $self->ut_snumber('pkgnum')
+ $self->ut_number('pkgnum')
|| $self->ut_number('invnum')
|| $self->ut_money('setup')
|| $self->ut_money('recur')
@@ -167,8 +163,7 @@ sub check {
;
return $error if $error;
- #if ( $self->pkgnum != 0 ) { #allow unchecked pkgnum 0 for tax! (add to part_pkg?)
- if ( $self->pkgnum > 0 ) { #allow -1 for non-pkg line items and 0 for tax (add to part_pkg?)
+ if ( $self->pkgnum != 0 ) { #allow unchecked pkgnum 0 for tax! (add to part_pkg?)
return "Unknown pkgnum ". $self->pkgnum
unless qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
}
@@ -205,33 +200,6 @@ sub details {
#qsearch ( 'cust_bill_pkg_detail', { 'lineitemnum' => $self->lineitemnum });
}
-=item desc
-
-Returns a description for this line item. For typical line items, this is the
-I<pkg> field of the corresponding B<FS::part_pkg> object (see L<FS::part_pkg>).
-For one-shot line items and named taxes, it is the I<itemdesc> field of this
-line item, and for generic taxes, simply returns "Tax".
-
-=cut
-
-sub desc {
- my $self = shift;
-
- if ( $self->pkgnum > 0 ) {
- $self->cust_pkg->part_pkg->pkg;
- } else {
- $self->itemdesc || 'Tax';
- }
-}
-
-=back
-
-=head1 CLASS METHODS
-
-=over 4
-
-=item
-
=back
=head1 BUGS
diff --git a/FS/FS/cust_bill_pkg_detail.pm b/FS/FS/cust_bill_pkg_detail.pm
index 4156816c8..261aa80ea 100644
--- a/FS/FS/cust_bill_pkg_detail.pm
+++ b/FS/FS/cust_bill_pkg_detail.pm
@@ -103,7 +103,7 @@ sub check {
$self->ut_numbern('detailnum')
|| $self->ut_foreign_key('pkgnum', 'cust_pkg', 'pkgnum')
- || $self->ut_foreign_key('invnum', 'cust_bill', 'invnum')
+ || $self->ut_foreign_key('invnum', 'cust_pkg', 'invnum')
|| $self->ut_text('detail')
|| $self->SUPER::check
;
diff --git a/FS/FS/cust_credit.pm b/FS/FS/cust_credit.pm
index 9cc92d2e8..026b92e84 100644
--- a/FS/FS/cust_credit.pm
+++ b/FS/FS/cust_credit.pm
@@ -4,14 +4,13 @@ use strict;
use vars qw( @ISA $conf $unsuspendauto );
use Date::Format;
use FS::UID qw( dbh getotaker );
-use FS::Misc qw(send_email);
use FS::Record qw( qsearch qsearchs );
-use FS::cust_main_Mixin;
+use FS::Misc qw(send_email);
use FS::cust_main;
use FS::cust_refund;
use FS::cust_credit_bill;
-@ISA = qw( FS::cust_main_Mixin FS::Record );
+@ISA = qw( FS::Record );
#ask FS::UID to run this stuff for us later
$FS::UID::callback{'FS::cust_credit'} = sub {
@@ -76,12 +75,6 @@ Creates a new credit. To add the credit to the database, see L<"insert">.
=cut
sub table { 'cust_credit'; }
-sub cust_linked { $_[0]->cust_main_custnum; }
-sub cust_unlinked_msg {
- my $self = shift;
- "WARNING: can't find cust_main.custnum ". $self->custnum.
- ' (cust_credit.crednum '. $self->crednum. ')';
-}
=item insert
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index a265e4177..44fb8d696 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -1,8 +1,7 @@
package FS::cust_main;
use strict;
-use vars qw( @ISA @EXPORT_OK $DEBUG $me $conf @encrypted_fields
- $import $skip_fuzzyfiles $ignore_expired_card );
+use vars qw( @ISA @EXPORT_OK $conf $DEBUG $import );
use vars qw( $realtime_bop_decline_quiet ); #ugh
use Safe;
use Carp;
@@ -14,17 +13,14 @@ BEGIN {
#eval "use Time::Local qw(timelocal timelocal_nocheck);";
eval "use Time::Local qw(timelocal_nocheck);";
}
-use Digest::MD5 qw(md5_base64);
use Date::Format;
#use Date::Manip;
use String::Approx qw(amatch);
-use Business::CreditCard 0.28;
+use Business::CreditCard;
use FS::UID qw( getotaker dbh );
use FS::Record qw( qsearchs qsearch dbdef );
use FS::Misc qw( send_email );
-use FS::Msgcat qw(gettext);
use FS::cust_pkg;
-use FS::cust_svc;
use FS::cust_bill;
use FS::cust_bill_pkg;
use FS::cust_pay;
@@ -44,9 +40,7 @@ use FS::part_bill_event;
use FS::cust_bill_event;
use FS::cust_tax_exempt;
use FS::type_pkgs;
-use FS::payment_gateway;
-use FS::agent_payment_gateway;
-use FS::banned_pay;
+use FS::Msgcat qw(gettext);
@ISA = qw( FS::Record );
@@ -54,17 +48,10 @@ use FS::banned_pay;
$realtime_bop_decline_quiet = 0;
-# 1 is mostly method/subroutine entry and options
-# 2 traces progress of some operations
-# 3 is even more information including possibly sensitive data
$DEBUG = 0;
-$me = '[FS::cust_main]';
+#$DEBUG = 1;
$import = 0;
-$skip_fuzzyfiles = 0;
-$ignore_expired_card = 0;
-
-@encrypted_fields = ('payinfo', 'paycvv');
#ask FS::UID to run this stuff for us later
#$FS::UID::callback{'FS::cust_main'} = sub {
@@ -188,94 +175,16 @@ FS::Record. The following fields are currently supported:
=item ship_fax - phone (optional)
-=item payby
-
-I<CARD> (credit card - automatic), I<DCRD> (credit card - on-demand), I<CHEK> (electronic check - automatic), I<DCHK> (electronic check - on-demand), I<LECB> (Phone bill billing), I<BILL> (billing), I<COMP> (free), or I<PREPAY> (special billing type: applies a credit - see L<FS::prepay_credit> and sets billing type to I<BILL>)
-
-=item payinfo
-
-Card Number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L<FS::prepay_credit>)
-
-=cut
-
-sub payinfo {
- my($self,$payinfo) = @_;
- if ( defined($payinfo) ) {
- $self->paymask($payinfo);
- $self->setfield('payinfo', $payinfo); # This is okay since we are the 'setter'
- } else {
- $payinfo = $self->getfield('payinfo'); # This is okay since we are the 'getter'
- return $payinfo;
- }
-}
-
-
-=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
-
-=cut
-
-=item paymask - Masked payment type
-
-=over 4
-
-=item Credit Cards
-
-Mask all but the last four characters.
-
-=item Checks
-
-Mask all but last 2 of account number and bank routing number.
-
-=item Others
-
-Do nothing, return the unmasked string.
+=item payby - I<CARD> (credit card - automatic), I<DCRD> (credit card - on-demand), I<CHEK> (electronic check - automatic), I<DCHK> (electronic check - on-demand), I<LECB> (Phone bill billing), I<BILL> (billing), I<COMP> (free), or I<PREPAY> (special billing type: applies a credit - see L<FS::prepay_credit> and sets billing type to I<BILL>)
-=back
-
-=cut
-
-sub paymask {
- my($self,$value)=@_;
+=item payinfo - card number, P.O., comp issuer (4-8 lowercase alphanumerics; think username) or prepayment identifier (see L<FS::prepay_credit>)
- # If it doesn't exist then generate it
- my $paymask=$self->getfield('paymask');
- if (!defined($value) && (!defined($paymask) || $paymask eq '')) {
- $value = $self->payinfo;
- }
-
- if ( defined($value) && !$self->is_encrypted($value)) {
- my $payinfo = $value;
- my $payby = $self->payby;
- if ($payby eq 'CARD' || $payby eq 'DCRD') { # Credit Cards (Show last four)
- $paymask = 'x'x(length($payinfo)-4). substr($payinfo,(length($payinfo)-4));
- } elsif ($payby eq 'CHEK' ||
- $payby eq 'DCHK' ) { # Checks (Show last 2 @ bank)
- my( $account, $aba ) = split('@', $payinfo );
- $paymask = 'x'x(length($account)-2). substr($account,(length($account)-2))."@".$aba;
- } else { # Tie up loose ends
- $paymask = $payinfo;
- }
- $self->setfield('paymask', $paymask); # This is okay since we are the 'setter'
- } elsif (defined($value) && $self->is_encrypted($value)) {
- $paymask = 'N/A';
- }
- return $paymask;
-}
+=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 paystart_month - start date month (maestro/solo cards only)
-
-=item paystart_year - start date year (maestro/solo cards only)
-
-=item payissue - issue number (maestro/solo cards only)
-
=item payname - name on card or billing name
-=item payip - IP address from which payment information was received
-
=item tax - tax exempt, empty or `Y'
=item otaker - order taker (assigned automatically, see L<FS::UID>)
@@ -347,7 +256,7 @@ sub insert {
my $cust_pkgs = @_ ? shift : {};
my $invoicing_list = @_ ? shift : '';
my %options = @_;
- warn "$me insert called with options ".
+ warn "FS::cust_main::insert called with options ".
join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
if $DEBUG;
@@ -362,38 +271,27 @@ sub insert {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- my $prepay_identifier = '';
- my( $amount, $seconds ) = ( 0, 0 );
- my $payby = '';
+ my $amount = 0;
+ my $seconds = 0;
if ( $self->payby eq 'PREPAY' ) {
-
$self->payby('BILL');
- $prepay_identifier = $self->payinfo;
- $self->payinfo('');
-
- warn " looking up prepaid card $prepay_identifier\n"
- if $DEBUG > 1;
-
- my $error = $self->get_prepay($prepay_identifier, \$amount, \$seconds);
+ my $prepay_credit = qsearchs(
+ 'prepay_credit',
+ { 'identifier' => $self->payinfo },
+ '',
+ 'FOR UPDATE'
+ );
+ warn "WARNING: can't find pre-found prepay_credit: ". $self->payinfo
+ unless $prepay_credit;
+ $amount = $prepay_credit->amount;
+ $seconds = $prepay_credit->seconds;
+ my $error = $prepay_credit->delete;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- #return "error applying prepaid card (transaction rolled back): $error";
- return $error;
+ return "removing prepay_credit (transaction rolled back): $error";
}
-
- $payby = 'PREP' if $amount;
-
- } elsif ( $self->payby =~ /^(CASH|WEST|MCRD)$/ ) {
-
- $payby = $1;
- $self->payby('BILL');
- $amount = $self->paid;
-
}
- warn " inserting $self\n"
- if $DEBUG > 1;
-
my $error = $self->SUPER::insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
@@ -401,9 +299,7 @@ sub insert {
return $error;
}
- warn " setting invoicing list\n"
- if $DEBUG > 1;
-
+ # invoicing list
if ( $invoicing_list ) {
$error = $self->check_invoicing_list( $invoicing_list );
if ( $error ) {
@@ -413,9 +309,7 @@ sub insert {
$self->invoicing_list( $invoicing_list );
}
- warn " ordering packages\n"
- if $DEBUG > 1;
-
+ # packages
$error = $self->order_pkgs($cust_pkgs, \$seconds, %options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
@@ -428,28 +322,23 @@ sub insert {
}
if ( $amount ) {
- warn " inserting initial $payby payment of $amount\n"
- if $DEBUG > 1;
- $error = $self->insert_cust_pay($payby, $amount, $prepay_identifier);
+ my $cust_credit = new FS::cust_credit {
+ 'custnum' => $self->custnum,
+ 'amount' => $amount,
+ };
+ $error = $cust_credit->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return "inserting payment (transaction rolled back): $error";
+ return "inserting credit (transaction rolled back): $error";
}
}
- unless ( $import || $skip_fuzzyfiles ) {
- warn " queueing fuzzyfiles update\n"
- if $DEBUG > 1;
- $error = $self->queue_fuzzyfiles_update;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "updating fuzzy search cache: $error";
- }
+ $error = $self->queue_fuzzyfiles_update;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "updating fuzzy search cache: $error";
}
- warn " insert complete; committing transaction\n"
- if $DEBUG > 1;
-
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
@@ -470,9 +359,6 @@ be a better explanation of this, but until then, here's an example:
);
$cust_main->order_pkgs( \%hash, \'0', 'noexport'=>1 );
-Services can be new, in which case they are inserted, or existing unaudited
-services, in which case they are linked to the newly-created package.
-
Currently available options are: I<depend_jobnum> and I<noexport>.
If I<depend_jobnum> is set, all provisioning jobs will have a dependancy
@@ -496,7 +382,7 @@ sub order_pkgs {
my %svc_options = ();
$svc_options{'depend_jobnum'} = $options{'depend_jobnum'}
if exists $options{'depend_jobnum'};
- warn "$me order_pkgs called with options ".
+ warn "FS::cust_main::order_pkgs called with options ".
join(', ', map { "$_: $options{$_}" } keys %options ). "\n"
if $DEBUG;
@@ -521,19 +407,12 @@ sub order_pkgs {
return "inserting cust_pkg (transaction rolled back): $error";
}
foreach my $svc_something ( @{$cust_pkgs->{$cust_pkg}} ) {
- if ( $svc_something->svcnum ) {
- my $old_cust_svc = $svc_something->cust_svc;
- my $new_cust_svc = new FS::cust_svc { $old_cust_svc->hash };
- $new_cust_svc->pkgnum( $cust_pkg->pkgnum);
- $error = $new_cust_svc->replace($old_cust_svc);
- } else {
- $svc_something->pkgnum( $cust_pkg->pkgnum );
- if ( $seconds && $$seconds && $svc_something->isa('FS::svc_acct') ) {
- $svc_something->seconds( $svc_something->seconds + $$seconds );
- $$seconds = 0;
- }
- $error = $svc_something->insert(%svc_options);
+ $svc_something->pkgnum( $cust_pkg->pkgnum );
+ if ( $seconds && $$seconds && $svc_something->isa('FS::svc_acct') ) {
+ $svc_something->seconds( $svc_something->seconds + $$seconds );
+ $$seconds = 0;
}
+ $error = $svc_something->insert(%svc_options);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
#return "inserting svc_ (transaction rolled back): $error";
@@ -546,223 +425,6 @@ sub order_pkgs {
''; #no error
}
-=item recharge_prepay IDENTIFIER | PREPAY_CREDIT_OBJ [ , AMOUNTREF, SECONDSREF ]
-
-Recharges this (existing) customer with the specified prepaid card (see
-L<FS::prepay_credit>), specified either by I<identifier> or as an
-FS::prepay_credit object. If there is an error, returns the error, otherwise
-returns false.
-
-Optionally, two scalar references can be passed as well. They will have their
-values filled in with the amount and number of seconds applied by this prepaid
-card.
-
-=cut
-
-sub recharge_prepay {
- my( $self, $prepay_credit, $amountref, $secondsref ) = @_;
-
- 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( $amount, $seconds ) = ( 0, 0 );
-
- my $error = $self->get_prepay($prepay_credit, \$amount, \$seconds)
- || $self->increment_seconds($seconds)
- || $self->insert_cust_pay_prepay( $amount,
- ref($prepay_credit)
- ? $prepay_credit->identifier
- : $prepay_credit
- );
-
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- if ( defined($amountref) ) { $$amountref = $amount; }
- if ( defined($secondsref) ) { $$secondsref = $seconds; }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-=item get_prepay IDENTIFIER | PREPAY_CREDIT_OBJ , AMOUNTREF, SECONDSREF
-
-Looks up and deletes a prepaid card (see L<FS::prepay_credit>),
-specified either by I<identifier> or as an FS::prepay_credit object.
-
-References to I<amount> and I<seconds> scalars should be passed as arguments
-and will be incremented by the values of the prepaid card.
-
-If the prepaid card specifies an I<agentnum> (see L<FS::agent>), it is used to
-check or set this customer's I<agentnum>.
-
-If there is an error, returns the error, otherwise returns false.
-
-=cut
-
-
-sub get_prepay {
- my( $self, $prepay_credit, $amountref, $secondsref ) = @_;
-
- 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;
-
- unless ( ref($prepay_credit) ) {
-
- my $identifier = $prepay_credit;
-
- $prepay_credit = qsearchs(
- 'prepay_credit',
- { 'identifier' => $prepay_credit },
- '',
- 'FOR UPDATE'
- );
-
- unless ( $prepay_credit ) {
- $dbh->rollback if $oldAutoCommit;
- return "Invalid prepaid card: ". $identifier;
- }
-
- }
-
- if ( $prepay_credit->agentnum ) {
- if ( $self->agentnum && $self->agentnum != $prepay_credit->agentnum ) {
- $dbh->rollback if $oldAutoCommit;
- return "prepaid card not valid for agent ". $self->agentnum;
- }
- $self->agentnum($prepay_credit->agentnum);
- }
-
- my $error = $prepay_credit->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "removing prepay_credit (transaction rolled back): $error";
- }
-
- $$amountref += $prepay_credit->amount;
- $$secondsref += $prepay_credit->seconds;
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-=item increment_seconds SECONDS
-
-Updates this customer's single or primary account (see L<FS::svc_acct>) by
-the specified number of seconds. If there is an error, returns the error,
-otherwise returns false.
-
-=cut
-
-sub increment_seconds {
- my( $self, $seconds ) = @_;
- warn "$me increment_seconds called: $seconds seconds\n"
- if $DEBUG;
-
- my @cust_pkg = grep { $_->part_pkg->svcpart('svc_acct') }
- $self->ncancelled_pkgs;
-
- if ( ! @cust_pkg ) {
- return 'No packages with primary or single services found'.
- ' to apply pre-paid time';
- } elsif ( scalar(@cust_pkg) > 1 ) {
- #maybe have a way to specify the package/account?
- return 'Multiple packages found to apply pre-paid time';
- }
-
- my $cust_pkg = $cust_pkg[0];
- warn " found package pkgnum ". $cust_pkg->pkgnum. "\n"
- if $DEBUG > 1;
-
- my @cust_svc =
- $cust_pkg->cust_svc( $cust_pkg->part_pkg->svcpart('svc_acct') );
-
- if ( ! @cust_svc ) {
- return 'No account found to apply pre-paid time';
- } elsif ( scalar(@cust_svc) > 1 ) {
- return 'Multiple accounts found to apply pre-paid time';
- }
-
- my $svc_acct = $cust_svc[0]->svc_x;
- warn " found service svcnum ". $svc_acct->pkgnum.
- ' ('. $svc_acct->email. ")\n"
- if $DEBUG > 1;
-
- $svc_acct->increment_seconds($seconds);
-
-}
-
-=item insert_cust_pay_prepay AMOUNT [ PAYINFO ]
-
-Inserts a prepayment in the specified amount for this customer. An optional
-second argument can specify the prepayment identifier for tracking purposes.
-If there is an error, returns the error, otherwise returns false.
-
-=cut
-
-sub insert_cust_pay_prepay {
- shift->insert_cust_pay('PREP', @_);
-}
-
-=item insert_cust_pay_cash AMOUNT [ PAYINFO ]
-
-Inserts a cash payment in the specified amount for this customer. An optional
-second argument can specify the payment identifier for tracking purposes.
-If there is an error, returns the error, otherwise returns false.
-
-=cut
-
-sub insert_cust_pay_cash {
- shift->insert_cust_pay('CASH', @_);
-}
-
-=item insert_cust_pay_west AMOUNT [ PAYINFO ]
-
-Inserts a Western Union payment in the specified amount for this customer. An
-optional second argument can specify the prepayment identifier for tracking
-purposes. If there is an error, returns the error, otherwise returns false.
-
-=cut
-
-sub insert_cust_pay_west {
- shift->insert_cust_pay('WEST', @_);
-}
-
-sub insert_cust_pay {
- my( $self, $payby, $amount ) = splice(@_, 0, 3);
- my $payinfo = scalar(@_) ? shift : '';
-
- my $cust_pay = new FS::cust_pay {
- 'custnum' => $self->custnum,
- 'paid' => sprintf('%.2f', $amount),
- #'_date' => #date the prepaid card was purchased???
- 'payby' => $payby,
- 'payinfo' => $payinfo,
- };
- $cust_pay->insert;
-
-}
-
=item reexport
This method is deprecated. See the I<depend_jobnum> option to the insert and
@@ -777,7 +439,7 @@ otherwise returns false.
sub reexport {
my $self = shift;
- carp "WARNING: FS::cust_main::reexport is deprectated; ".
+ carp "warning: FS::cust_main::reexport is deprectated; ".
"use the depend_jobnum option to insert or order_pkgs to delay export";
local $SIG{HUP} = 'IGNORE';
@@ -929,27 +591,12 @@ sub replace {
local $SIG{TSTP} = 'IGNORE';
local $SIG{PIPE} = 'IGNORE';
- # If the mask is blank then try to set it - if we can...
- if (!defined($self->getfield('paymask')) || $self->getfield('paymask') eq '') {
- $self->paymask($self->payinfo);
- }
-
- # We absolutely have to have an old vs. new record to make this work.
- if (!defined($old)) {
- $old = qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
- }
-
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');
}
- local($ignore_expired_card) = 1
- if $old->payby =~ /^(CARD|DCRD)$/
- && $self->payby =~ /^(CARD|DCRD)$/
- && $old->payinfo eq $self->payinfo;
-
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
@@ -981,12 +628,10 @@ sub replace {
}
}
- unless ( $import || $skip_fuzzyfiles ) {
- $error = $self->queue_fuzzyfiles_update;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "updating fuzzy search cache: $error";
- }
+ $error = $self->queue_fuzzyfiles_update;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "updating fuzzy search cache: $error";
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
@@ -1039,15 +684,14 @@ sub queue_fuzzyfiles_update {
Checks all fields to make sure this is a valid customer record. If there is
an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
+and repalce methods.
=cut
sub check {
my $self = shift;
- warn "$me check BEFORE: \n". $self->_dump
- if $DEBUG > 2;
+ #warn "BEFORE: \n". $self->_dump;
my $error =
$self->ut_numbern('custnum')
@@ -1076,7 +720,7 @@ sub check {
return "Unknown refnum"
unless qsearchs( 'part_referral', { 'refnum' => $self->refnum } );
- return "Unknown referring custnum: ". $self->referral_custnum
+ return "Unknown referring custnum ". $self->referral_custnum
unless ! $self->referral_custnum
|| qsearchs( 'cust_main', { 'custnum' => $self->referral_custnum } );
@@ -1146,7 +790,7 @@ sub check {
} ) ) {
return "Unknown ship_state/ship_county/ship_country: ".
$self->ship_state. "/". $self->ship_county. "/". $self->ship_country
- unless qsearch('cust_main_county',{
+ unless qsearchs('cust_main_county',{
'state' => $self->ship_state,
'county' => $self->ship_county,
'country' => $self->ship_country,
@@ -1169,34 +813,11 @@ sub check {
}
}
- $self->payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP|PREPAY|CASH|WEST|MCRD)$/
+ $self->payby =~ /^(CARD|DCRD|CHEK|DCHK|LECB|BILL|COMP|PREPAY)$/
or return "Illegal payby: ". $self->payby;
-
- $error = $self->ut_numbern('paystart_month')
- || $self->ut_numbern('paystart_year')
- || $self->ut_numbern('payissue')
- ;
- return $error if $error;
-
- if ( $self->payip eq '' ) {
- $self->payip('');
- } else {
- $error = $self->ut_ip('payip');
- return $error if $error;
- }
-
- # If it is encrypted and the private key is not availaible then we can't
- # check the credit card.
-
- my $check_payinfo = 1;
-
- if ($self->is_encrypted($self->payinfo)) {
- $check_payinfo = 0;
- }
-
$self->payby($1);
- if ( $check_payinfo && $self->payby =~ /^(CARD|DCRD)$/ ) {
+ if ( $self->payby eq 'CARD' || $self->payby eq 'DCRD' ) {
my $payinfo = $self->payinfo;
$payinfo =~ s/\D//g;
@@ -1206,15 +827,10 @@ sub check {
$self->payinfo($payinfo);
validate($payinfo)
or return gettext('invalid_card'); # . ": ". $self->payinfo;
-
return gettext('unknown_card_type')
if cardtype($self->payinfo) eq "Unknown";
-
- my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref);
- return "Banned credit card" if $ban;
-
if ( defined $self->dbdef_table->column('paycvv') ) {
- if (length($self->paycvv) && !$self->is_encrypted($self->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.";
@@ -1229,31 +845,7 @@ sub check {
}
}
- my $cardtype = cardtype($payinfo);
- if ( $cardtype =~ /^(Switch|Solo)$/i ) {
-
- return "Start date or issue number is required for $cardtype cards"
- unless $self->paystart_month && $self->paystart_year or $self->payissue;
-
- return "Start month must be between 1 and 12"
- if $self->paystart_month
- and $self->paystart_month < 1 || $self->paystart_month > 12;
-
- return "Start year must be 1990 or later"
- if $self->paystart_year
- and $self->paystart_year < 1990;
-
- return "Issue number must be beween 1 and 99"
- if $self->payissue
- and $self->payissue < 1 || $self->payissue > 99;
-
- } else {
- $self->paystart_month('');
- $self->paystart_year('');
- $self->payissue('');
- }
-
- } elsif ( $check_payinfo && $self->payby =~ /^(CHEK|DCHK)$/ ) {
+ } elsif ( $self->payby eq 'CHEK' || $self->payby eq 'DCHK' ) {
my $payinfo = $self->payinfo;
$payinfo =~ s/[^\d\@]//g;
@@ -1262,9 +854,6 @@ sub check {
$self->payinfo($payinfo);
$self->paycvv('') if $self->dbdef_table->column('paycvv');
- my $ban = qsearchs('banned_pay', $self->_banned_pay_hashref);
- return "Banned ACH account" if $ban;
-
} elsif ( $self->payby eq 'LECB' ) {
my $payinfo = $self->payinfo;
@@ -1306,7 +895,7 @@ sub check {
if ( $self->paydate eq '' || $self->paydate eq '-' ) {
return "Expriation date required"
- unless $self->payby =~ /^(BILL|PREPAY|CHEK|DCHK|LECB|CASH|WEST|MCRD)$/;
+ unless $self->payby =~ /^(BILL|PREPAY|CHEK|LECB)$/;
$self->paydate('');
} else {
my( $m, $y );
@@ -1320,9 +909,7 @@ sub check {
$self->paydate("$y-$m-01");
my($nowm,$nowy)=(localtime(time))[4,5]; $nowm++; $nowy+=1900;
return gettext('expired_card')
- if !$import
- && !$ignore_expired_card
- && ( $y<$nowy || ( $y==$nowy && $1<$nowm ) );
+ if !$import && ( $y<$nowy || ( $y==$nowy && $1<$nowm ) );
}
if ( $self->payname eq '' && $self->payby !~ /^(CHEK|DCHK)$/ &&
@@ -1331,7 +918,7 @@ sub check {
) {
$self->payname( $self->first. " ". $self->getfield('last') );
} else {
- $self->payname =~ /^([\w \,\.\-\'\&]+)$/
+ $self->payname =~ /^([\w \,\.\-\']+)$/
or return gettext('illegal_name'). " payname: ". $self->payname;
$self->payname($1);
}
@@ -1341,8 +928,7 @@ sub check {
$self->otaker(getotaker) unless $self->otaker;
- warn "$me check AFTER: \n". $self->_dump
- if $DEBUG > 2;
+ #warn "AFTER: \n". $self->_dump;
$self->SUPER::check;
}
@@ -1460,8 +1046,7 @@ sub unsuspend {
=item suspend
Suspends all unsuspended packages (see L<FS::cust_pkg>) for this customer.
-
-Returns a list: an empty list on success or a list of errors.
+Always returns a list: an empty list on success or a list of errors.
=cut
@@ -1473,9 +1058,8 @@ sub suspend {
=item suspend_if_pkgpart PKGPART [ , PKGPART ... ]
Suspends all unsuspended packages (see L<FS::cust_pkg>) matching the listed
-PKGPARTs (see L<FS::part_pkg>).
-
-Returns a list: an empty list on success or a list of errors.
+PKGPARTs (see L<FS::part_pkg>). Always returns a list: an empty list on
+success or a list of errors.
=cut
@@ -1490,9 +1074,8 @@ sub suspend_if_pkgpart {
=item suspend_unless_pkgpart PKGPART [ , PKGPART ... ]
Suspends all unsuspended packages (see L<FS::cust_pkg>) unless they match the
-listed PKGPARTs (see L<FS::part_pkg>).
-
-Returns a list: an empty list on success or a list of errors.
+listed PKGPARTs (see L<FS::part_pkg>). Always returns a list: an empty list
+on success or a list of errors.
=cut
@@ -1508,56 +1091,19 @@ sub suspend_unless_pkgpart {
Cancels all uncancelled packages (see L<FS::cust_pkg>) for this customer.
-Available options are: I<quiet>, I<reasonnum>, and I<ban>
+Available options are: I<quiet>
I<quiet> can be set true to supress email cancellation notices.
-# I<reasonnum> can be set to a cancellation reason (see L<FS::cancel_reason>)
-
-I<ban> can be set true to ban this customer's credit card or ACH information,
-if present.
-
Always returns a list: an empty list on success or a list of errors.
=cut
sub cancel {
my $self = shift;
- my %opt = @_;
-
- if ( $opt{'ban'} && $self->payby =~ /^(CARD|DCRD|CHEK|DCHK)$/ ) {
-
- #should try decryption (we might have the private key)
- # and if not maybe queue a job for the server that does?
- return ( "Can't (yet) ban encrypted credit cards" )
- if $self->is_encrypted($self->payinfo);
-
- my $ban = new FS::banned_pay $self->_banned_pay_hashref;
- my $error = $ban->insert;
- return ( $error ) if $error;
-
- }
-
grep { $_ } map { $_->cancel(@_) } $self->ncancelled_pkgs;
}
-sub _banned_pay_hashref {
- my $self = shift;
-
- my %payby2ban = (
- 'CARD' => 'CARD',
- 'DCRD' => 'CARD',
- 'CHEK' => 'CHEK',
- 'DCHK' => 'CHEK'
- );
-
- {
- 'payby' => $payby2ban{$self->payby},
- 'payinfo' => md5_base64($self->payinfo),
- #'reason' =>
- };
-}
-
=item agent
Returns the agent (see L<FS::agent>) for this customer.
@@ -1596,8 +1142,7 @@ If there is an error, returns the error, otherwise returns false.
sub bill {
my( $self, %options ) = @_;
return '' if $self->payby eq 'COMP';
- warn "$me bill customer ". $self->custnum. "\n"
- if $DEBUG;
+ warn "bill customer ". $self->custnum if $DEBUG;
my $time = $options{'time'} || time;
@@ -1636,7 +1181,7 @@ sub bill {
#NO!! next if $cust_pkg->cancel;
next if $cust_pkg->getfield('cancel');
- warn " bill package ". $cust_pkg->pkgnum. "\n" if $DEBUG > 1;
+ warn " bill package ". $cust_pkg->pkgnum if $DEBUG;
#? to avoid use of uninitialized value errors... ?
$cust_pkg->setfield('bill', '')
@@ -1653,7 +1198,7 @@ sub bill {
my $setup = 0;
if ( !$cust_pkg->setup || $options{'resetup'} ) {
- warn " bill setup\n" if $DEBUG > 1;
+ warn " bill setup" if $DEBUG;
$setup = eval { $cust_pkg->calc_setup( $time ) };
if ( $@ ) {
@@ -1672,7 +1217,7 @@ sub bill {
( $cust_pkg->getfield('bill') || 0 ) <= $time
) {
- warn " bill recur\n" if $DEBUG > 1;
+ warn " bill recur" if $DEBUG;
# XXX shared with $recur_prog
$sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
@@ -1704,9 +1249,6 @@ sub bill {
} elsif ( $part_pkg->freq =~ /^(\d+)d$/ ) {
my $days = $1;
$mday += $days;
- } elsif ( $part_pkg->freq =~ /^(\d+)h$/ ) {
- my $hours = $1;
- $hour += $hours;
} else {
$dbh->rollback if $oldAutoCommit;
return "unparsable frequency: ". $part_pkg->freq;
@@ -1721,8 +1263,7 @@ sub bill {
if ( $cust_pkg->modified ) {
- warn " package ". $cust_pkg->pkgnum. " modified; updating\n"
- if $DEBUG >1;
+ warn " package ". $cust_pkg->pkgnum. " modified; updating\n" if $DEBUG;
$error=$cust_pkg->replace($old_cust_pkg);
if ( $error ) { #just in case
@@ -1742,7 +1283,7 @@ sub bill {
}
if ( $setup != 0 || $recur != 0 ) {
warn " charges (setup=$setup, recur=$recur); queueing line items\n"
- if $DEBUG > 1;
+ if $DEBUG;
my $cust_bill_pkg = new FS::cust_bill_pkg ({
'pkgnum' => $cust_pkg->pkgnum,
'setup' => $setup,
@@ -1802,7 +1343,7 @@ sub bill {
|| $tax->recurtax =~ /^Y$/i;
next unless $taxable_charged;
- if ( $tax->exempt_amount && $tax->exempt_amount > 0 ) {
+ if ( $tax->exempt_amount > 0 ) {
my ($mon,$year) = (localtime($sdate) )[4,5];
$mon++;
my $freq = $part_pkg->freq || 1;
@@ -2009,8 +1550,7 @@ sub collect {
$self->select_for_update; #mutex
my $balance = $self->balance;
- warn "$me collect customer ". $self->custnum. ": balance $balance\n"
- if $DEBUG;
+ warn "collect customer ". $self->custnum. ": balance $balance" if $DEBUG;
unless ( $balance > 0 ) { #redundant?????
$dbh->rollback if $oldAutoCommit; #hmm
return '';
@@ -2035,8 +1575,8 @@ sub collect {
last if $self->balance <= 0;
- warn " invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ")\n"
- if $DEBUG > 1;
+ warn "invnum ". $cust_bill->invnum. " (owed ". $cust_bill->owed. ")"
+ if $DEBUG;
foreach my $part_bill_event (
sort { $a->seconds <=> $b->seconds
@@ -2056,8 +1596,8 @@ sub collect {
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 > 1;
+ warn "calling invoice event (". $part_bill_event->eventcode. ")\n"
+ if $DEBUG;
my $cust_main = $self; #for callback
my $error;
@@ -2197,84 +1737,31 @@ I<quiet> can be set true to surpress email decline notices.
sub realtime_bop {
my( $self, $method, $amount, %options ) = @_;
if ( $DEBUG ) {
- warn "$me realtime_bop: $method $amount\n";
+ warn "$self $method $amount\n";
warn " $_ => $options{$_}\n" foreach keys %options;
}
$options{'description'} ||= 'Internet services';
+ #pre-requisites
+ die "Real-time processing not enabled\n"
+ unless $conf->exists('business-onlinepayment');
eval "use Business::OnlinePayment";
die $@ if $@;
- my $payinfo = exists($options{'payinfo'})
- ? $options{'payinfo'}
- : $self->payinfo;
-
- ###
- # select a gateway
- ###
-
- my $taxclass = '';
- if ( $options{'invnum'} ) {
- my $cust_bill = qsearchs('cust_bill', { 'invnum' => $options{'invnum'} } );
- die "invnum ". $options{'invnum'}. " not found" unless $cust_bill;
- my @taxclasses =
- map { $_->part_pkg->taxclass }
- grep { $_ }
- map { $_->cust_pkg }
- $cust_bill->cust_bill_pkg;
- unless ( grep { $taxclasses[0] ne $_ } @taxclasses ) { #unless there are
- #different taxclasses
- $taxclass = $taxclasses[0];
- }
- }
-
- #look for an agent gateway override first
- my $cardtype;
- if ( $method eq 'CC' ) {
- $cardtype = cardtype($payinfo);
- } elsif ( $method eq 'ECHECK' ) {
- $cardtype = 'ACH';
- } else {
- $cardtype = $method;
- }
-
- my $override =
- qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => $cardtype,
- taxclass => $taxclass, } )
- || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => '',
- taxclass => $taxclass, } )
- || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => $cardtype,
- taxclass => '', } )
- || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => '',
- taxclass => '', } );
-
- my $payment_gateway = '';
- my( $processor, $login, $password, $action, @bop_options );
- if ( $override ) { #use a payment gateway override
-
- $payment_gateway = $override->payment_gateway;
-
- $processor = $payment_gateway->gateway_module;
- $login = $payment_gateway->gateway_username;
- $password = $payment_gateway->gateway_password;
- $action = $payment_gateway->gateway_action;
- @bop_options = $payment_gateway->options;
-
- } else { #use the standard settings from the config
-
- ( $processor, $login, $password, $action, @bop_options ) =
- $self->default_payment_gateway($method);
-
- }
+ #load up config
+ my $bop_config = 'business-onlinepayment';
+ $bop_config .= '-ach'
+ if $method eq 'ECHECK' && $conf->exists($bop_config. '-ach');
+ my ( $processor, $login, $password, $action, @bop_options ) =
+ $conf->config($bop_config);
+ $action ||= 'normal authorization';
+ pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
+ die "No real-time processor is enabled - ".
+ "did you set the business-onlinepayment configuration value?\n"
+ unless $processor;
- ###
- # massage data
- ###
+ #massage data
my $address = exists($options{'address1'})
? $options{'address1'}
@@ -2303,19 +1790,13 @@ sub realtime_bop {
|| ( $conf->exists('emailinvoiceonly') && ! @invoicing_list ) ) {
push @invoicing_list, $self->all_emails;
}
+ my $email = $invoicing_list[0];
- my $email = ($conf->exists('business-onlinepayment-email-override'))
- ? $conf->config('business-onlinepayment-email-override')
- : $invoicing_list[0];
+ my $payinfo = exists($options{'payinfo'})
+ ? $options{'payinfo'}
+ : $self->payinfo;
my %content = ();
-
- my $payip = exists($options{'payip'})
- ? $options{'payip'}
- : $self->payip;
- $content{customer_ip} = $payip
- if length($payip);
-
if ( $method eq 'CC' ) {
$content{card_number} = $payinfo;
@@ -2325,27 +1806,13 @@ sub realtime_bop {
$paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
$content{expiration} = "$2/$1";
- my $paycvv = exists($options{'paycvv'})
- ? $options{'paycvv'}
- : $self->paycvv;
- $content{cvv2} = $self->paycvv
- if length($paycvv);
-
- my $paystart_month = exists($options{'paystart_month'})
- ? $options{'paystart_month'}
- : $self->paystart_month;
-
- my $paystart_year = exists($options{'paystart_year'})
- ? $options{'paystart_year'}
- : $self->paystart_year;
-
- $content{card_start} = "$paystart_month/$paystart_year"
- if $paystart_month && $paystart_year;
-
- my $payissue = exists($options{'payissue'})
- ? $options{'payissue'}
- : $self->payissue;
- $content{issue_number} = $payissue if $payissue;
+ if ( defined $self->dbdef_table->column('paycvv') ) {
+ my $paycvv = exists($options{'paycvv'})
+ ? $options{'paycvv'}
+ : $self->paycvv;
+ $content{cvv2} = $self->paycvv
+ if length($paycvv);
+ }
$content{recurring_billing} = 'YES'
if qsearch('cust_pay', { 'custnum' => $self->custnum,
@@ -2367,9 +1834,7 @@ sub realtime_bop {
$content{phone} = $payinfo;
}
- ###
- # run transaction(s)
- ###
+ #transaction(s)
my( $action1, $action2 ) = split(/\s*\,\s*/, $action );
@@ -2447,10 +1912,7 @@ sub realtime_bop {
}
- ###
- # remove paycvv after initial transaction
- ###
-
+ #remove paycvv after initial transaction
#false laziness w/misc/process/payment.cgi - check both to make sure working
# correctly
if ( defined $self->dbdef_table->column('paycvv')
@@ -2459,14 +1921,11 @@ sub realtime_bop {
) {
my $error = $self->remove_cvv;
if ( $error ) {
- warn "WARNING: error removing cvv: $error\n";
+ warn "error removing cvv: $error\n";
}
}
- ###
- # result handling
- ###
-
+ #result handling
if ( $transaction->is_success() ) {
my %method2payby = (
@@ -2475,13 +1934,7 @@ sub realtime_bop {
'LEC' => 'LECB',
);
- my $paybatch = '';
- if ( $payment_gateway ) { # agent override
- $paybatch = $payment_gateway->gatewaynum. '-';
- }
-
- $paybatch .= "$processor:". $transaction->authorization;
-
+ my $paybatch = "$processor:". $transaction->authorization;
$paybatch .= ':'. $transaction->order_number
if $transaction->can('order_number')
&& length($transaction->order_number);
@@ -2548,31 +2001,6 @@ sub realtime_bop {
}
-=item default_payment_gateway
-
-=cut
-
-sub default_payment_gateway {
- my( $self, $method ) = @_;
-
- die "Real-time processing not enabled\n"
- unless $conf->exists('business-onlinepayment');
-
- #load up config
- my $bop_config = 'business-onlinepayment';
- $bop_config .= '-ach'
- if $method eq 'ECHECK' && $conf->exists($bop_config. '-ach');
- my ( $processor, $login, $password, $action, @bop_options ) =
- $conf->config($bop_config);
- $action ||= 'normal authorization';
- pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
- die "No real-time processor is enabled - ".
- "did you set the business-onlinepayment configuration value?\n"
- unless $processor;
-
- ( $processor, $login, $password, $action, @bop_options )
-}
-
=item remove_cvv
Removes the I<paycvv> field from the database directly.
@@ -2629,98 +2057,43 @@ gateway is attempted.
sub realtime_refund_bop {
my( $self, $method, %options ) = @_;
if ( $DEBUG ) {
- warn "$me realtime_refund_bop: $method refund\n";
+ warn "$self $method refund\n";
warn " $_ => $options{$_}\n" foreach keys %options;
}
+ #pre-requisites
+ die "Real-time processing not enabled\n"
+ unless $conf->exists('business-onlinepayment');
eval "use Business::OnlinePayment";
die $@ if $@;
- ###
- # look up the original payment and optionally a gateway for that payment
- ###
+ #load up config
+ my $bop_config = 'business-onlinepayment';
+ $bop_config .= '-ach'
+ if $method eq 'ECHECK' && $conf->exists($bop_config. '-ach');
+ my ( $processor, $login, $password, $unused_action, @bop_options ) =
+ $conf->config($bop_config);
+ #$action ||= 'normal authorization';
+ pop @bop_options if scalar(@bop_options) % 2 && $bop_options[-1] =~ /^\s*$/;
+ die "No real-time processor is enabled - ".
+ "did you set the business-onlinepayment configuration value?\n"
+ unless $processor;
my $cust_pay = '';
my $amount = $options{'amount'};
-
- my( $processor, $login, $password, @bop_options ) ;
- my( $auth, $order_number ) = ( '', '', '' );
-
+ my( $pay_processor, $auth, $order_number ) = ( '', '', '' );
if ( $options{'paynum'} ) {
-
- warn " paynum: $options{paynum}\n" if $DEBUG > 1;
+ warn "FS::cust_main::realtime_bop: paynum: $options{paynum}\n" if $DEBUG;
$cust_pay = qsearchs('cust_pay', { paynum=>$options{'paynum'} } )
or return "Unknown paynum $options{'paynum'}";
$amount ||= $cust_pay->paid;
-
- $cust_pay->paybatch =~ /^((\d+)\-)?(\w+):\s*([\w\-]*)(:([\w\-]+))?$/
+ $cust_pay->paybatch =~ /^(\w+):(\w*)(:(\w+))?$/
or return "Can't parse paybatch for paynum $options{'paynum'}: ".
$cust_pay->paybatch;
- my $gatewaynum = '';
- ( $gatewaynum, $processor, $auth, $order_number ) = ( $2, $3, $4, $6 );
-
- if ( $gatewaynum ) { #gateway for the payment to be refunded
-
- my $payment_gateway =
- qsearchs('payment_gateway', { 'gatewaynum' => $gatewaynum } );
- die "payment gateway $gatewaynum not found"
- unless $payment_gateway;
-
- $processor = $payment_gateway->gateway_module;
- $login = $payment_gateway->gateway_username;
- $password = $payment_gateway->gateway_password;
- @bop_options = $payment_gateway->options;
-
- } else { #try the default gateway
-
- my( $conf_processor, $unused_action );
- ( $conf_processor, $login, $password, $unused_action, @bop_options ) =
- $self->default_payment_gateway($method);
-
- return "processor of payment $options{'paynum'} $processor does not".
- " match default processor $conf_processor"
- unless $processor eq $conf_processor;
-
- }
-
-
- } else { # didn't specify a paynum, so look for agent gateway overrides
- # like a normal transaction
-
- my $cardtype;
- if ( $method eq 'CC' ) {
- $cardtype = cardtype($self->payinfo);
- } elsif ( $method eq 'ECHECK' ) {
- $cardtype = 'ACH';
- } else {
- $cardtype = $method;
- }
- my $override =
- qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => $cardtype,
- taxclass => '', } )
- || qsearchs('agent_payment_gateway', { agentnum => $self->agentnum,
- cardtype => '',
- taxclass => '', } );
-
- if ( $override ) { #use a payment gateway override
-
- my $payment_gateway = $override->payment_gateway;
-
- $processor = $payment_gateway->gateway_module;
- $login = $payment_gateway->gateway_username;
- $password = $payment_gateway->gateway_password;
- #$action = $payment_gateway->gateway_action;
- @bop_options = $payment_gateway->options;
-
- } else { #use the standard settings from the config
-
- my $unused_action;
- ( $processor, $login, $password, $unused_action, @bop_options ) =
- $self->default_payment_gateway($method);
-
- }
-
+ ( $pay_processor, $auth, $order_number ) = ( $1, $2, $4 );
+ return "processor of payment $options{'paynum'} $pay_processor does not".
+ " match current processor $processor"
+ unless $pay_processor eq $processor;
}
return "neither amount nor paynum specified" unless $amount;
@@ -2738,7 +2111,6 @@ sub realtime_refund_bop {
#first try void if applicable
if ( $cust_pay && $cust_pay->paid == $amount ) { #and check dates?
- warn " attempting void\n" if $DEBUG > 1;
my $void = new Business::OnlinePayment( $processor, @bop_options );
$void->content( 'action' => 'void', %content );
$void->submit();
@@ -2751,14 +2123,10 @@ sub realtime_refund_bop {
warn $e;
return $e;
}
- warn " void successful\n" if $DEBUG > 1;
return '';
}
}
- warn " void unsuccessful, trying refund\n"
- if $DEBUG > 1;
-
#massage data
my $address = $self->address1;
$address .= ", ". $self->address2 if $self->address2;
@@ -2775,34 +2143,36 @@ sub realtime_refund_bop {
$payname = "$payfirst $paylast";
}
- my $payinfo = '';
- if ( $method eq 'CC' ) {
+ if ( $method eq 'CC' ) {
- if ( $cust_pay ) {
- $content{card_number} = $payinfo = $cust_pay->payinfo;
- #$self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
- #$content{expiration} = "$2/$1";
- } else {
- $content{card_number} = $payinfo = $self->payinfo;
- $self->paydate =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/;
- $content{expiration} = "$2/$1";
- }
+ $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' ) {
( $content{account_number}, $content{routing_code} ) =
- split('@', $payinfo = $self->payinfo);
+ split('@', $self->payinfo);
$content{bank_name} = $self->payname;
$content{account_type} = 'CHECKING';
$content{account_name} = $payname;
$content{customer_org} = $self->company ? 'B' : 'I';
$content{customer_ssn} = $self->ss;
} elsif ( $method eq 'LEC' ) {
- $content{phone} = $payinfo = $self->payinfo;
+ $content{phone} = $self->payinfo;
}
#then try refund
my $refund = new Business::OnlinePayment( $processor, @bop_options );
- my %sub_content = $refund->content(
+ $refund->content(
'action' => 'credit',
'customer_id' => $self->custnum,
'last_name' => $paylast,
@@ -2815,8 +2185,6 @@ sub realtime_refund_bop {
'country' => $self->country,
%content, #after
);
- warn join('', map { " $_ => $sub_content{$_}\n" } keys %sub_content )
- if $DEBUG > 1;
$refund->submit();
return "$processor error: ". $refund->error_message
@@ -2846,7 +2214,7 @@ sub realtime_refund_bop {
'refund' => $amount,
'_date' => '',
'payby' => $method2payby{$method},
- 'payinfo' => $payinfo,
+ 'payinfo' => $self->payinfo,
'paybatch' => $paybatch,
'reason' => $options{'reason'} || 'card or ACH refund',
} );
@@ -3094,17 +2462,15 @@ sub paydate_monthyear {
=item payinfo_masked
-Returns a "masked" payinfo field appropriate to the payment type. Masked characters are replaced by 'x'es. Use this to display publicly accessable account Information.
-
-Credit Cards - Mask all but the last four characters.
-Checks - Mask all but last 2 of account number and bank routing number.
-Others - Do nothing, return the unmasked string.
+Returns a "masked" payinfo field with all but the last four characters replaced
+by 'x'es. Useful for displaying credit cards.
=cut
sub payinfo_masked {
my $self = shift;
- return $self->paymask;
+ my $payinfo = $self->payinfo;
+ 'x'x(length($payinfo)-4). substr($payinfo,(length($payinfo)-4));
}
=item invoicing_list [ ARRAYREF ]
@@ -3176,11 +2542,6 @@ is an error, returns the error, otherwise returns false.
sub check_invoicing_list {
my( $self, $arrayref ) = @_;
foreach my $address ( @{$arrayref} ) {
-
- if ($address eq 'FAX' and $self->getfield('fax') eq '') {
- return 'Can\'t add FAX invoice destination with a blank FAX number.';
- }
-
my $cust_main_invoice = new FS::cust_main_invoice ( {
'custnum' => $self->custnum,
'dest' => $address,
@@ -3298,19 +2659,6 @@ sub referral_cust_pkg {
$self->referral_cust_main($depth);
}
-=item referring_cust_main
-
-Returns the single cust_main record for the customer who referred this customer
-(referral_custnum), or false.
-
-=cut
-
-sub referring_cust_main {
- my $self = shift;
- return '' unless $self->referral_custnum;
- qsearchs('cust_main', { 'custnum' => $self->referral_custnum } );
-}
-
=item credit AMOUNT, REASON
Applies a credit to this customer. If there is an error, returns the error,
@@ -3491,53 +2839,11 @@ Returns a name string for this customer, either "Company (Last, First)" or
sub name {
my $self = shift;
- my $name = $self->contact;
+ my $name = $self->get('last'). ', '. $self->first;
$name = $self->company. " ($name)" if $self->company;
$name;
}
-=item ship_name
-
-Returns a name string for this (service/shipping) contact, either
-"Company (Last, First)" or "Last, First".
-
-=cut
-
-sub ship_name {
- my $self = shift;
- if ( $self->get('ship_last') ) {
- my $name = $self->ship_contact;
- $name = $self->ship_company. " ($name)" if $self->ship_company;
- $name;
- } else {
- $self->name;
- }
-}
-
-=item contact
-
-Returns this customer's full (billing) contact name only, "Last, First"
-
-=cut
-
-sub contact {
- my $self = shift;
- $self->get('last'). ', '. $self->first;
-}
-
-=item ship_contact
-
-Returns this customer's full (shipping) contact name only, "Last, First"
-
-=cut
-
-sub ship_contact {
- my $self = shift;
- $self->get('ship_last')
- ? $self->get('ship_last'). ', '. $self->ship_first
- : $self->contact;
-}
-
=item status
Returns a status string for this customer, currently:
@@ -3612,7 +2918,8 @@ Returns an SQL expression identifying active cust_main records.
sub active_sql { "
0 < ( SELECT COUNT(*) FROM cust_pkg
WHERE cust_pkg.custnum = cust_main.custnum
- AND ". FS::cust_pkg->active_sql. "
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
+ AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
)
"; }
@@ -3623,22 +2930,16 @@ Returns an SQL expression identifying suspended cust_main records.
=cut
-#my $recurring_sql = FS::cust_pkg->recurring_sql;
-my $recurring_sql = "
- '0' != ( select freq from part_pkg
- where cust_pkg.pkgpart = part_pkg.pkgpart )
-";
-
sub suspended_sql { susp_sql(@_); }
sub susp_sql { "
0 < ( SELECT COUNT(*) FROM cust_pkg
WHERE cust_pkg.custnum = cust_main.custnum
- AND $recurring_sql
AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
)
AND 0 = ( SELECT COUNT(*) FROM cust_pkg
WHERE cust_pkg.custnum = cust_main.custnum
- AND ". FS::cust_pkg->active_sql. "
+ AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
+ AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
)
"; }
@@ -3656,7 +2957,6 @@ sub cancel_sql { "
)
AND 0 = ( SELECT COUNT(*) FROM cust_pkg
WHERE cust_pkg.custnum = cust_main.custnum
- AND $recurring_sql
AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
)
"; }
diff --git a/FS/FS/cust_main_Mixin.pm b/FS/FS/cust_main_Mixin.pm
deleted file mode 100644
index a114c5a8a..000000000
--- a/FS/FS/cust_main_Mixin.pm
+++ /dev/null
@@ -1,103 +0,0 @@
-package FS::cust_main_Mixin;
-
-use strict;
-use FS::cust_main;
-
-=head1 NAME
-
-FS::cust_main_Mixin - Mixin class for records that contain fields from cust_main
-
-=head1 SYNOPSIS
-
-package FS::some_table;
-use vars qw(@ISA);
-@ISA = qw( FS::cust_main_Mixin FS::Record );
-
-=head1 DESCRIPTION
-
-This is a mixin class for records that contain fields from the cust_main table,
-for example, from a JOINed search. See httemplate/search/ for examples.
-
-=head1 METHODS
-
-=over 4
-
-=item name
-
-Given an object that contains fields from cust_main (say, from a JOINed
-search; see httemplate/search/ for examples), returns the equivalent of the
-FS::cust_main I<name> method, or "(unlinked)" if this object is not linked to
-a customer.
-
-=cut
-
-sub cust_unlinked_msg { '(unlinked)'; }
-sub cust_linked { $_[0]->custnum; }
-
-sub name {
- my $self = shift;
- $self->cust_linked
- ? FS::cust_main::name($self)
- : $self->cust_unlinked_msg;
-}
-
-=item ship_name
-
-Given an object that contains fields from cust_main (say, from a JOINed
-search; see httemplate/search/ for examples), returns the equivalent of the
-FS::cust_main I<ship_name> method, or "(unlinked)" if this object is not
-linked to a customer.
-
-=cut
-
-sub ship_name {
- my $self = shift;
- $self->cust_linked
- ? FS::cust_main::ship_name($self)
- : $self->cust_unlinked_msg;
-}
-
-=item contact
-
-Given an object that contains fields from cust_main (say, from a JOINed
-search; see httemplate/search/ for examples), returns the equivalent of the
-FS::cust_main I<contact> method, or "(unlinked)" if this object is not linked
-to a customer.
-
-=cut
-
-sub contact {
- my $self = shift;
- $self->cust_linked
- ? FS::cust_main::contact($self)
- : $self->cust_unlinked_msg;
-}
-
-=item ship_contact
-
-Given an object that contains fields from cust_main (say, from a JOINed
-search; see httemplate/search/ for examples), returns the equivalent of the
-FS::cust_main I<ship_contact> method, or "(unlinked)" if this object is not
-linked to a customer.
-
-=cut
-
-sub ship_contact {
- my $self = shift;
- $self->cust_linked
- ? FS::cust_main::ship_contact($self)
- : $self->cust_unlinked_msg;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::cust_main>, L<FS::Record>
-
-=cut
-
-1;
-
diff --git a/FS/FS/cust_main_county.pm b/FS/FS/cust_main_county.pm
index 17f346071..d96bd41de 100644
--- a/FS/FS/cust_main_county.pm
+++ b/FS/FS/cust_main_county.pm
@@ -196,9 +196,8 @@ END
foreach my $country ( sort keys %cust_main_county ) {
$script_html .= "\nif ( country == \"$country\" ) {\n";
foreach my $state ( sort keys %{$cust_main_county{$country}} ) {
- ( my $dstate = $state ) =~ s/[\n\r]//g;
- my $text = $dstate || '(n/a)';
- $script_html .= qq!opt(what.form.${prefix}state, "$dstate", "$text");\n!;
+ my $text = $state || '(n/a)';
+ $script_html .= qq!opt(what.form.${prefix}state, "$state", "$text");\n!;
}
$script_html .= "}\n";
}
@@ -251,7 +250,7 @@ END
foreach my $state ( sort keys %{ $cust_main_county{$selected_country} } ) {
my $text = $state || '(n/a)';
my $selected = $state eq $selected_state ? 'SELECTED' : '';
- $state_html .= qq(\n<OPTION $selected VALUE="$state">$text</OPTION>);
+ $state_html .= "\n<OPTION $selected VALUE=$state>$text</OPTION>"
}
$state_html .= '</SELECT>';
@@ -265,7 +264,7 @@ END
keys %cust_main_county
) {
my $selected = $country eq $selected_country ? ' SELECTED' : '';
- $country_html .= qq(\n<OPTION$selected VALUE="$country">$country</OPTION>");
+ $country_html .= "\n<OPTION$selected>$country</OPTION>"
}
$country_html .= '</SELECT>';
diff --git a/FS/FS/cust_main_invoice.pm b/FS/FS/cust_main_invoice.pm
index 48f47e0cd..3cabd3a64 100644
--- a/FS/FS/cust_main_invoice.pm
+++ b/FS/FS/cust_main_invoice.pm
@@ -43,7 +43,7 @@ FS::Record. The following fields are currently supported:
=item custnum - customer (see L<FS::cust_main>)
-=item dest - Invoice destination: If numeric, a svcnum (see L<FS::svc_acct>), if string, a literal email address, `POST' to enable mailing (the default if no cust_main_invoice records exist), or `FAX' to enable faxing via a HylaFAX server.
+=item dest - Invoice destination: If numeric, a svcnum (see L<FS::svc_acct>), if string, a literal email address, or `POST' to enable mailing (the default if no cust_main_invoice records exist)
=back
@@ -127,7 +127,7 @@ sub checkdest {
my $error = $self->ut_text('dest');
return $error if $error;
- if ( $self->dest =~ /^(POST|FAX)$/ ) {
+ if ( $self->dest eq 'POST' ) {
#contemplate our navel
} elsif ( $self->dest =~ /^(\d+)$/ ) {
return "Unknown local account (specified by svcnum: ". $self->dest. ")"
@@ -136,7 +136,7 @@ sub checkdest {
my($user, $domain) = ($1, $2);
$self->dest("$1\@$2");
} else {
- return gettext("illegal_email_invoice_address"). ': '. $self->dest;
+ return gettext("illegal_email_invoice_address");
}
''; #no error
@@ -144,7 +144,7 @@ sub checkdest {
=item address
-Returns the literal email address for this record (or `POST' or `FAX').
+Returns the literal email address for this record (or `POST').
=cut
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index f057d2faf..1ceb599a0 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -1,22 +1,19 @@
package FS::cust_pay;
use strict;
-use vars qw( @ISA $conf $unsuspendauto $ignore_noapply );
+use vars qw( @ISA $conf $unsuspendauto );
use Date::Format;
use Business::CreditCard;
use Text::Template;
-use FS::Misc qw(send_email);
use FS::Record qw( dbh qsearch qsearchs );
-use FS::cust_main_Mixin;
+use FS::Misc qw(send_email);
use FS::cust_bill;
use FS::cust_bill_pay;
use FS::cust_pay_refund;
use FS::cust_main;
use FS::cust_pay_void;
-@ISA = qw( FS::cust_main_Mixin FS::Record );
-
-$ignore_noapply = 0;
+@ISA = qw( FS::Record );
#ask FS::UID to run this stuff for us later
FS::UID->install_callback( sub {
@@ -61,9 +58,7 @@ currently supported:
L<Time::Local> and L<Date::Parse> for conversion functions.
=item payby - `CARD' (credit cards), `CHEK' (electronic check/ACH),
-`LECB' (phone bill billing), `BILL' (billing), `PREP` (prepaid card),
-`CASH' (cash), `WEST' (Western Union), `MCRD' (Manual credit card), or
-`COMP' (free)
+`LECB' (phone bill billing), `BILL' (billing), or `COMP' (free)
=item payinfo - card number, check #, or comp issuer (4-8 lowercase alphanumerics; think username), respectively
@@ -84,12 +79,6 @@ Creates a new payment. To add the payment to the databse, see L<"insert">.
=cut
sub table { 'cust_pay'; }
-sub cust_linked { $_[0]->cust_main_custnum; }
-sub cust_unlinked_msg {
- my $self = shift;
- "WARNING: can't find cust_main.custnum ". $self->custnum.
- ' (cust_pay.paynum '. $self->paynum. ')';
-}
=item insert
@@ -124,13 +113,12 @@ sub insert {
$self->custnum($cust_bill->custnum );
}
+ my $cust_main = $self->cust_main;
+ my $old_balance = $cust_main->balance;
my $error = $self->check;
return $error if $error;
- my $cust_main = $self->cust_main;
- my $old_balance = $cust_main->balance;
-
$error = $self->SUPER::insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
@@ -146,13 +134,8 @@ sub insert {
};
$error = $cust_bill_pay->insert;
if ( $error ) {
- if ( $ignore_noapply ) {
- warn "warning: error inserting $cust_bill_pay: $error ".
- "(ignore_noapply flag set; inserting cust_pay record anyway)\n";
- } else {
- $dbh->rollback if $oldAutoCommit;
- return "error inserting $cust_bill_pay: $error";
- }
+ $dbh->rollback if $oldAutoCommit;
+ return "error inserting $cust_bill_pay: $error";
}
}
@@ -184,7 +167,7 @@ sub insert {
#my $cust_main = $self->cust_main;
if ( $conf->exists('payment_receipt_email')
- && grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list
+ && grep { $_ ne 'POST' } $cust_main->invoicing_list
) {
my $receipt_template = new Text::Template (
@@ -195,13 +178,12 @@ sub insert {
return '';
};
- my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list;
+ my @invoicing_list = grep { $_ ne 'POST' } $cust_main->invoicing_list;
my $payby = $self->payby;
my $payinfo = $self->payinfo;
$payby =~ s/^BILL$/Check/ if $payinfo;
- $payinfo = $self->payinfo_masked if $payby eq 'CARD' || $payby eq 'CHEK';
- $payby =~ s/^CHEK$/Electronic check/;
+ $payinfo = $self->payinfo_masked if $payby eq 'CARD';
my $error = send_email(
'from' => $conf->config('invoice_from'), #??? well as good as any
@@ -375,8 +357,7 @@ sub check {
$self->_date(time) unless $self->_date;
- $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|PREP|CASH|WEST|MCRD)$/
- or return "Illegal payby";
+ $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP)$/ or return "Illegal payby";
$self->payby($1);
#false laziness with cust_refund::check
@@ -402,61 +383,6 @@ sub check {
$self->SUPER::check;
}
-=item batch_insert CUST_PAY_OBJECT, ...
-
-Class method which inserts multiple payments. Takes a list of FS::cust_pay
-objects. Returns a list, each element representing the status of inserting the
-corresponding payment - empty. If there is an error inserting any payment, the
-entire transaction is rolled back, i.e. all payments are inserted or none are.
-
-For example:
-
- my @errors = FS::cust_pay->batch_insert(@cust_pay);
- my $num_errors = scalar(grep $_, @errors);
- if ( $num_errors == 0 ) {
- #success; all payments were inserted
- } else {
- #failure; no payments were inserted.
- }
-
-=cut
-
-sub batch_insert {
- my $self = shift; #class method
-
- 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 $errors = 0;
-
- my @errors = map {
- my $error = $_->insert;
- if ( $error ) {
- $errors++;
- } else {
- $_->cust_main->apply_payments;
- }
- $error;
- } @_;
-
- if ( $errors ) {
- $dbh->rollback if $oldAutoCommit;
- } else {
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- }
-
- @errors;
-
-}
-
=item cust_bill_pay
Returns all applications to invoices (see L<FS::cust_bill_pay>) for this
@@ -538,16 +464,8 @@ by 'x'es. Useful for displaying credit cards.
sub payinfo_masked {
my $self = shift;
- #some false laziness w/cust_main::paymask
- if ( $self->payby eq 'CARD' ) {
- my $payinfo = $self->payinfo;
- 'x'x(length($payinfo)-4). substr($payinfo,(length($payinfo)-4));
- } elsif ( $self->payby eq 'CHEK' ) {
- my( $account, $aba ) = split('@', $self->payinfo );
- 'x'x(length($account)-2). substr($account,(length($account)-2)). "@". $aba;
- } else {
- $self->payinfo;
- }
+ my $payinfo = $self->payinfo;
+ 'x'x(length($payinfo)-4). substr($payinfo,(length($payinfo)-4));
}
=back
diff --git a/FS/FS/cust_pay_refund.pm b/FS/FS/cust_pay_refund.pm
index 15e0e533a..af25f1774 100644
--- a/FS/FS/cust_pay_refund.pm
+++ b/FS/FS/cust_pay_refund.pm
@@ -138,26 +138,26 @@ sub check {
$self->SUPER::check;
}
-=item sub cust_pay
+=item sub cust_credit
-Returns the payment (see L<FS::cust_pay>)
+Returns the credit (see L<FS::cust_credit>)
=cut
-sub cust_pay {
+sub cust_credit {
my $self = shift;
- qsearchs( 'cust_pay', { 'paynum' => $self->paynum } );
+ qsearchs( 'cust_credit', { 'crednum' => $self->crednum } );
}
-=item cust_refund
+=item cust_bill
-Returns the refund (see L<FS::cust_refund>)
+Returns the invoice (see L<FS::cust_bill>)
=cut
-sub cust_refund {
+sub cust_bill {
my $self = shift;
- qsearchs( 'cust_refund', { 'refundnum' => $self->refundnum } );
+ qsearchs( 'cust_bill', { 'invnum' => $self->invnum } );
}
=back
diff --git a/FS/FS/cust_pay_void.pm b/FS/FS/cust_pay_void.pm
index 946d69fe1..7267929c8 100644
--- a/FS/FS/cust_pay_void.pm
+++ b/FS/FS/cust_pay_void.pm
@@ -3,8 +3,7 @@ use strict;
use vars qw( @ISA );
use Business::CreditCard;
use FS::UID qw(getotaker);
-use FS::Record qw(qsearchs dbh fields); # qsearch );
-use FS::cust_pay;
+use FS::Record qw(qsearchs); # dbh qsearch );
#use FS::cust_bill;
#use FS::cust_bill_pay;
#use FS::cust_pay_refund;
@@ -48,8 +47,7 @@ are currently supported:
L<Time::Local> and L<Date::Parse> for conversion functions.
=item payby - `CARD' (credit cards), `CHEK' (electronic check/ACH),
-`LECB' (phone bill billing), `BILL' (billing), `CASH' (cash),
-`WEST' (Western Union), `MCRD' (Manual credit card), or `COMP' (free)
+`LECB' (phone bill billing), `BILL' (billing), or `COMP' (free)
=item payinfo - card number, check #, or comp issuer (4-8 lowercase alphanumerics; think username), respectively
@@ -79,53 +77,16 @@ sub table { 'cust_pay_void'; }
Adds this voided payment to the database.
-=item unvoid
+=item delete
-"Un-void"s this payment: Deletes the voided payment from the database and adds
-back a normal payment.
+Currently unimplemented.
=cut
-sub unvoid {
- 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;
-
- my $cust_pay = new FS::cust_pay ( {
- map { $_ => $self->get($_) } fields('cust_pay')
- } );
- my $error = $cust_pay->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- $error = $self->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- '';
-
+sub delete {
+ return "Can't delete voided payments!";
}
-=item delete
-
-Deletes this voided payment. You probably don't want to use this directly; see
-the B<unvoid> method to add the original payment back.
-
=item replace OLD_RECORD
Currently unimplemented.
@@ -167,8 +128,7 @@ sub check {
$self->void_date(time) unless $self->void_date;
- $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|PREP|CASH|WEST|MCRD)$/
- or return "Illegal payby";
+ $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP)$/ or return "Illegal payby";
$self->payby($1);
#false laziness with cust_refund::check
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index 783cc73a3..ced142398 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -3,9 +3,8 @@ package FS::cust_pkg;
use strict;
use vars qw(@ISA $disable_agentcheck @SVCDB_CANCEL_SEQ $DEBUG);
use FS::UID qw( getotaker dbh );
-use FS::Misc qw( send_email );
use FS::Record qw( qsearch qsearchs );
-use FS::cust_main_Mixin;
+use FS::Misc qw( send_email );
use FS::cust_svc;
use FS::part_pkg;
use FS::cust_main;
@@ -13,11 +12,10 @@ use FS::type_pkgs;
use FS::pkg_svc;
use FS::cust_bill_pkg;
use FS::h_cust_svc;
-use FS::reg_code;
# need to 'use' these instead of 'require' in sub { cancel, suspend, unsuspend,
# setup }
-# because they load configuration by setting FS::UID::callback (see TODO)
+# because they load configuraion by setting FS::UID::callback (see TODO)
use FS::svc_acct;
use FS::svc_domain;
use FS::svc_www;
@@ -26,7 +24,7 @@ use FS::svc_forward;
# for sending cancel emails in sub cancel
use FS::Conf;
-@ISA = qw( FS::cust_main_Mixin FS::Record );
+@ISA = qw( FS::Record );
$DEBUG = 0;
@@ -142,14 +140,8 @@ Create a new billing item. To add the item to the database, see L<"insert">.
=cut
sub table { 'cust_pkg'; }
-sub cust_linked { $_[0]->cust_main_custnum; }
-sub cust_unlinked_msg {
- my $self = shift;
- "WARNING: can't find cust_main.custnum ". $self->custnum.
- ' (cust_pkg.pkgnum '. $self->pkgnum. ')';
-}
-=item insert [ OPTION => VALUE ... ]
+=item insert
Adds this billing item to the database ("Orders" the item). If there is an
error, returns the error, otherwise returns false.
@@ -158,82 +150,6 @@ If the additional field I<promo_code> is defined instead of I<pkgpart>, it
will be used to look up the package definition and agent restrictions will be
ignored.
-The following options are available: I<change>
-
-I<change>, if set true, supresses any referral credit to a referring customer.
-
-=cut
-
-sub insert {
- my( $self, %options ) = @_;
-
- 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 $error = $self->SUPER::insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- #if ( $self->reg_code ) {
- # my $reg_code = qsearchs('reg_code', { 'code' => $self->reg_code } );
- # $error = $reg_code->delete;
- # if ( $error ) {
- # $dbh->rollback if $oldAutoCommit;
- # return $error;
- # }
- #}
-
- my $conf = new FS::Conf;
- my $cust_main = $self->cust_main;
- my $part_pkg = $self->part_pkg;
- if ( $conf->exists('referral_credit')
- && $cust_main->referral_custnum
- && ! $options{'change'}
- && $part_pkg->freq !~ /^0\D?$/
- )
- {
- my $referring_cust_main = $cust_main->referring_cust_main;
- if ( $referring_cust_main->status ne 'cancelled' ) {
- my $error;
- if ( $part_pkg->freq !~ /^\d+$/ ) {
- warn 'WARNING: Not crediting customer '. $cust_main->referral_custnum.
- ' for package '. $self->pkgnum.
- ' ( customer '. $self->custnum. ')'.
- ' - One-time referral credits not (yet) available for '.
- ' packages with '. $part_pkg->freq_pretty. ' frequency';
- } else {
-
- my $amount = sprintf( "%.2f", $part_pkg->base_recur / $part_pkg->freq );
- my $error =
- $referring_cust_main->credit( $amount,
- 'Referral credit for '. $cust_main->name
- );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "Error crediting customer ". $cust_main->referral_custnum.
- " for referral: $error";
- }
-
- }
-
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
=item delete
This method now works but you probably shouldn't use it.
@@ -264,8 +180,6 @@ suspend is normally updated by the suspend and unsuspend methods.
cancel is normally updated by the cancel method (and also the order subroutine
in some cases).
-Calls
-
=cut
sub replace {
@@ -283,51 +197,7 @@ sub replace {
local($disable_agentcheck) = 1 if $old->pkgpart == $new->pkgpart;
- 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;
-
- #save off and freeze RADIUS attributes for any associated svc_acct records
- my @svc_acct = ();
- if ( $old->part_pkg->is_prepaid || $new->part_pkg->is_prepaid ) {
-
- #also check for specific exports?
- # to avoid spurious modify export events
- @svc_acct = map { $_->svc_x }
- grep { $_->part_svc->svcdb eq 'svc_acct' }
- $old->cust_svc;
-
- $_->snapshot foreach @svc_acct;
-
- }
-
- my $error = $new->SUPER::replace($old);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- #for prepaid packages,
- #trigger export of new RADIUS Expiration attribute when cust_pkg.bill changes
- foreach my $old_svc_acct ( @svc_acct ) {
- my $new_svc_acct = new FS::svc_acct { $old_svc_acct->hash };
- my $s_error = $new_svc_acct->replace($old_svc_acct);
- if ( $s_error ) {
- $dbh->rollback if $oldAutoCommit;
- return $s_error;
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
+ $new->SUPER::replace($old);
}
=item check
@@ -352,17 +222,7 @@ sub check {
;
return $error if $error;
- if ( $self->reg_code ) {
-
- unless ( grep { $self->pkgpart == $_->pkgpart }
- map { $_->reg_code_pkg }
- qsearchs( 'reg_code', { 'code' => $self->reg_code,
- 'agentnum' => $self->cust_main->agentnum })
- ) {
- return "Unknown registration code";
- }
-
- } elsif ( $self->promo_code ) {
+ if ( $self->promo_code ) {
my $promo_part_pkg =
qsearchs('part_pkg', {
@@ -370,6 +230,7 @@ sub check {
'promo_code' => { op=>'ILIKE', value=>$self->promo_code },
} );
return 'Unknown promotional code' unless $promo_part_pkg;
+ $self->pkgpart($promo_part_pkg->pkgpart);
} else {
@@ -448,20 +309,6 @@ sub cancel {
}
}
- # Add a credit for remaining service
- my $remaining_value = $self->calc_remain();
- if ( $remaining_value > 0 ) {
- my $error = $self->cust_main->credit(
- $remaining_value,
- 'Credit for unused time on '. $self->part_pkg->pkg,
- );
- if ($error) {
- $dbh->rollback if $oldAutoCommit;
- return "Error crediting customer \$$remaining_value for unused time on".
- $self->part_pkg->pkg. ": $error";
- }
- }
-
unless ( $self->getfield('cancel') ) {
my %hash = $self->hash;
$hash{'cancel'} = time;
@@ -476,7 +323,7 @@ sub cancel {
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
my $conf = new FS::Conf;
- my @invoicing_list = grep { $_ !~ /^(POST|FAX)$/ } $self->cust_main->invoicing_list;
+ my @invoicing_list = grep { $_ ne 'POST' } $self->cust_main->invoicing_list;
if ( !$options{'quiet'} && $conf->exists('emailcancel') && @invoicing_list ) {
my $conf = new FS::Conf;
my $error = send_email(
@@ -678,30 +525,6 @@ sub calc_recur {
$self->part_pkg->calc_recur($self, @_);
}
-=item calc_remain
-
-Calls the I<calc_remain> of the FS::part_pkg object associated with this
-billing item.
-
-=cut
-
-sub calc_remain {
- my $self = shift;
- $self->part_pkg->calc_remain($self, @_);
-}
-
-=item calc_cancel
-
-Calls the I<calc_cancel> of the FS::part_pkg object associated with this
-billing item.
-
-=cut
-
-sub calc_cancel {
- my $self = shift;
- $self->part_pkg->calc_cancel($self, @_);
-}
-
=item cust_svc [ SVCPART ]
Returns the services for this package, as FS::cust_svc objects (see
@@ -801,54 +624,6 @@ sub available_part_svc {
$self->part_pkg->pkg_svc;
}
-=item status
-
-Returns a short status string for this package, currently:
-
-=over 4
-
-=item not yet billed
-
-=item one-time charge
-
-=item active
-
-=item suspended
-
-=item cancelled
-
-=back
-
-=cut
-
-sub status {
- my $self = shift;
-
- return 'cancelled' if $self->get('cancel');
- return 'suspended' if $self->susp;
- return 'not yet billed' unless $self->setup;
- return 'one-time charge' if $self->part_pkg->freq =~ /^(0|$)/;
- return 'active';
-}
-
-=item statuscolor
-
-Returns a hex triplet color string for this package's status.
-
-=cut
-
-my %statuscolor = (
- 'not yet billed' => '000000',
- 'one-time charge' => '000000',
- 'active' => '00CC00',
- 'suspended' => 'FF9900',
- 'cancelled' => 'FF0000',
-);
-sub statuscolor {
- my $self = shift;
- $statuscolor{$self->status};
-}
-
=item labels
Returns a list of lists, calling the label method for all services
@@ -1163,60 +938,6 @@ sub reexport {
=back
-=head1 CLASS METHOD
-
-=over 4
-
-=item recurring_sql
-
-Returns an SQL expression identifying recurring packages.
-
-=cut
-
-sub recurring_sql { "
- '0' != ( select freq from part_pkg
- where cust_pkg.pkgpart = part_pkg.pkgpart )
-"; }
-
-=item active_sql
-
-Returns an SQL expression identifying active packages.
-
-=cut
-
-sub active_sql { "
- ". $_[0]->recurring_sql(). "
- AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
- AND ( cust_pkg.susp IS NULL OR cust_pkg.susp = 0 )
-"; }
-
-=item susp_sql
-=item suspended_sql
-
-Returns an SQL expression identifying suspended packages.
-
-=cut
-
-sub suspended_sql { susp_sql(@_); }
-sub susp_sql { "
- ". $_[0]->recurring_sql(). "
- AND ( cust_pkg.cancel IS NULL OR cust_pkg.cancel = 0 )
- AND cust_pkg.susp IS NOT NULL AND cust_pkg.susp != 0
-"; }
-
-=item cancel_sql
-=item cancelled_sql
-
-Returns an SQL exprression identifying cancelled packages.
-
-=cut
-
-sub cancelled_sql { cancel_sql(@_); }
-sub cancel_sql { "
- ". $_[0]->recurring_sql(). "
- AND cust_pkg.cancel IS NOT NULL AND cust_pkg.cancel != 0
-"; }
-
=head1 SUBROUTINES
=over 4
@@ -1261,24 +982,12 @@ sub order {
my $cust_main = qsearchs('cust_main', { custnum => $custnum });
return "Customer not found: $custnum" unless $cust_main;
- my @old_cust_pkg = map { qsearchs('cust_pkg', { pkgnum => $_ }) }
- @$remove_pkgnum;
-
- my $change = scalar(@old_cust_pkg) != 0;
-
- my %hash = ();
- if ( scalar(@old_cust_pkg) == 1 ) {
- #$hash{$_} = $old_cust_pkg[0]->$_() foreach qw( last_bill bill );
- $hash{'setup'} = time;
- }
-
# Create the new packages.
- foreach my $pkgpart (@$pkgparts) {
- my $cust_pkg = new FS::cust_pkg { custnum => $custnum,
- pkgpart => $pkgpart,
- %hash,
- };
- $error = $cust_pkg->insert( 'change' => $change );
+ my $cust_pkg;
+ foreach (@$pkgparts) {
+ $cust_pkg = new FS::cust_pkg { custnum => $custnum,
+ pkgpart => $_ };
+ $error = $cust_pkg->insert;
if ($error) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -1289,7 +998,8 @@ sub order {
# created packages.
# Transfer services and cancel old packages.
- foreach my $old_pkg (@old_cust_pkg) {
+ foreach my $old_pkgnum (@$remove_pkgnum) {
+ my $old_pkg = qsearchs ('cust_pkg', { pkgnum => $old_pkgnum });
foreach my $new_pkg (@$return_cust_pkg) {
$error = $old_pkg->transfer($new_pkg);
diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm
index 8c672b8d7..106ccd3c3 100644
--- a/FS/FS/cust_refund.pm
+++ b/FS/FS/cust_refund.pm
@@ -51,8 +51,7 @@ inherits from FS::Record. The following fields are currently supported:
L<Time::Local> and L<Date::Parse> for conversion functions.
=item payby - `CARD' (credit cards), `CHEK' (electronic check/ACH),
-`LECB' (Phone bill billing), `BILL' (billing), `CASH' (cash),
-`WEST' (Western Union), `MCRD' (Manual credit card), or `COMP' (free)
+`LECB' (Phone bill billing), `BILL' (billing), or `COMP' (free)
=item payinfo - card number, P.O.#, or comp issuer (4-8 lowercase alphanumerics; think username)
@@ -212,8 +211,7 @@ sub check {
unless $self->crednum
|| qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
- $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP|CASH|WEST|MCRD)$/
- or return "Illegal payby";
+ $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP)$/ or return "Illegal payby";
$self->payby($1);
#false laziness with cust_pay::check
diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm
index ad87cab7e..9cb7a8163 100644
--- a/FS/FS/cust_svc.pm
+++ b/FS/FS/cust_svc.pm
@@ -19,7 +19,7 @@ use FS::part_export;
@ISA = qw( FS::Record );
-$DEBUG = 0;
+$DEBUG = 1;
$ignore_quantity = 0;
@@ -178,7 +178,6 @@ sub replace {
if ( $new->svcpart != $old->svcpart ) {
my $svc_x = $new->svc_x;
my $new_svc_x = ref($svc_x)->new({$svc_x->hash, svcpart=>$new->svcpart });
- local($FS::Record::nowarn_identical) = 1;
my $error = $new_svc_x->replace($svc_x);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
@@ -200,7 +199,7 @@ sub replace {
=item check
Checks all fields to make sure this is a valid service. If there is an error,
-returns the error, otherwise returns false. Called by the insert and
+returns the error, otehrwise returns false. Called by the insert and
replace methods.
=cut
@@ -258,8 +257,8 @@ sub part_svc {
=item cust_pkg
-Returns the package this service belongs to, as a FS::cust_pkg object (see
-L<FS::cust_pkg>).
+Returns the definition for this service, as a FS::part_svc object (see
+L<FS::part_svc>).
=cut
@@ -274,7 +273,6 @@ Returns a list consisting of:
- The name of this service (from part_svc)
- A meaningful identifier (username, domain, or mail alias)
- The table name (i.e. svc_domain) for this service
-- svcnum
=cut
@@ -310,15 +308,14 @@ sub _svc_label {
} elsif ( $svcdb eq 'svc_domain' ) {
$tag = $svc_x->getfield('domain');
} elsif ( $svcdb eq 'svc_www' ) {
- my $domain_record = $svc_x->domain_record(@_);
+ my $domain_record = $svc_x->domain_record;
$tag = $domain_record->zone;
} elsif ( $svcdb eq 'svc_broadband' ) {
$tag = $svc_x->ip_addr;
} elsif ( $svcdb eq 'svc_external' ) {
my $conf = new FS::Conf;
if ( $conf->config('svc_external-display_type') eq 'artera_turbo' ) {
- $tag = sprintf('%010d', $svc_x->id). '-'.
- substr('0000000000'.uc($svc_x->title), -10);
+ $tag = sprintf('%010d', $svc_x->id). '-'. sprintf('%010d', $svc_x->title);
} else {
$tag = $svc_x->id. ': '. $svc_x->title;
}
@@ -327,7 +324,7 @@ sub _svc_label {
$tag = $svc_x->getfield('svcnum');
}
- $self->part_svc->svc, $tag, $svcdb, $self->svcnum;
+ $self->part_svc->svc, $tag, $svcdb;
}
@@ -384,9 +381,10 @@ sub seconds_since_sqlradacct {
my $svc_x = $self->svc_x;
- my @part_export = $self->part_svc->part_export_usage;
- die "no accounting-capable exports are enabled for ". $self->part_svc->svc.
- " service definition"
+ 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;
@@ -411,7 +409,14 @@ sub seconds_since_sqlradacct {
$str2time = 'extract(epoch from ';
}
- my $username = $part_export->export_username($svc_x);
+ 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;
@@ -493,9 +498,10 @@ sub attribute_since_sqlradacct {
my $svc_x = $self->svc_x;
- my @part_export = $self->part_svc->part_export_usage;
- die "no accounting-capable exports are enabled for ". $self->part_svc->svc.
- " service definition"
+ 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;
@@ -521,7 +527,14 @@ sub attribute_since_sqlradacct {
$str2time = 'extract(epoch from ';
}
- my $username = $part_export->export_username($svc_x);
+ 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
@@ -540,11 +553,11 @@ sub attribute_since_sqlradacct {
}
-=item get_session_history TIMESTAMP_START TIMESTAMP_END
+=item get_session_history_sqlradacct TIMESTAMP_START TIMESTAMP_END
-See L<FS::svc_acct/get_session_history>. Equivalent to
-$cust_svc->svc_x->get_session_history, but more efficient. Meaningless for
-records where B<svcdb> is not "svc_acct".
+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
@@ -553,20 +566,21 @@ sub get_session_history {
#$attrib ???
- my @part_export = $self->part_svc->part_export_usage;
- die "no accounting-capable exports are enabled for ". $self->part_svc->svc.
- " service definition"
+ #my @part_export = $cust_svc->part_svc->part_export->can('usage_sessions');
+ 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 @sessions = ();
foreach my $part_export ( @part_export ) {
- push @sessions,
- @{ $part_export->usage_sessions( $start, $end, $self->svc_x ) };
+ push @sessions, $part_export->usage_sessions( $start, $end, $self->svc_x );
}
- @sessions;
+ \@sessions;
}
diff --git a/FS/FS/domain_record.pm b/FS/FS/domain_record.pm
index 3c65a1a05..2a30594da 100644
--- a/FS/FS/domain_record.pm
+++ b/FS/FS/domain_record.pm
@@ -10,7 +10,7 @@ use FS::svc_www;
@ISA = qw(FS::Record);
-$DEBUG = 0;
+$DEBUG = 1;
=head1 NAME
@@ -250,23 +250,15 @@ sub check {
return "Unknown svcnum (in svc_domain)"
unless qsearchs('svc_domain', { 'svcnum' => $self->svcnum } );
- my $conf = new FS::Conf;
-
- if ( $conf->exists('zone-underscore') ) {
- $self->reczone =~ /^(@|[a-z0-9_\.\-\*]+)$/i
- or return "Illegal reczone: ". $self->reczone;
- $self->reczone($1);
- } else {
- $self->reczone =~ /^(@|[a-z0-9\.\-\*]+)$/i
- or return "Illegal reczone: ". $self->reczone;
- $self->reczone($1);
- }
+ $self->reczone =~ /^(@|[a-z0-9\.\-\*]+)$/i
+ or return "Illegal reczone: ". $self->reczone;
+ $self->reczone($1);
$self->recaf =~ /^(IN)$/ or return "Illegal recaf: ". $self->recaf;
$self->recaf($1);
- $self->rectype =~ /^(SOA|NS|MX|A|PTR|CNAME|TXT|_mstr)$/
- or return "Illegal rectype (only SOA NS MX A PTR CNAME TXT recognized): ".
+ $self->rectype =~ /^(SOA|NS|MX|A|PTR|CNAME|_mstr)$/
+ or return "Illegal rectype (only SOA NS MX A PTR CNAME recognized): ".
$self->rectype;
$self->rectype($1);
@@ -292,26 +284,13 @@ sub check {
or return "Illegal data for A record: ". $self->recdata;
$self->recdata($1);
} elsif ( $self->rectype eq 'PTR' ) {
- if ( $conf->exists('zone-underscore') ) {
- $self->recdata =~ /^([a-z0-9_\.\-]+)$/i
- or return "Illegal data for PTR record: ". $self->recdata;
- $self->recdata($1);
- } else {
- $self->recdata =~ /^([a-z0-9\.\-]+)$/i
- or return "Illegal data for PTR record: ". $self->recdata;
- $self->recdata($1);
- }
+ $self->recdata =~ /^([a-z0-9\.\-]+)$/i
+ or return "Illegal data for PTR record: ". $self->recdata;
+ $self->recdata($1);
} elsif ( $self->rectype eq 'CNAME' ) {
$self->recdata =~ /^([a-z0-9\.\-]+|\@)$/i
or return "Illegal data for CNAME record: ". $self->recdata;
$self->recdata($1);
- } elsif ( $self->rectype eq 'TXT' ) {
- if ( $self->recdata =~ /^((?:\S+)|(?:".+"))$/ ) {
- $self->recdata($1);
- } else {
- $self->recdata('"'. $self->recdata. '"'); #?
- }
- # or return "Illegal data for TXT record: ". $self->recdata;
} elsif ( $self->rectype eq '_mstr' ) {
$self->recdata =~ /^((\d{1,3}\.){3}\d{1,3})$/
or return "Illegal data for _master pseudo-record: ". $self->recdata;
diff --git a/FS/FS/export_svc.pm b/FS/FS/export_svc.pm
index 0370f5f0b..d1153c0fd 100644
--- a/FS/FS/export_svc.pm
+++ b/FS/FS/export_svc.pm
@@ -60,21 +60,16 @@ points to. You can ask the object for a copy with the I<hash> method.
sub table { 'export_svc'; }
-=item insert [ JOB, OFFSET, MULTIPLIER ]
+=item insert
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
-TODOC: JOB, OFFSET, MULTIPLIER
-
=cut
sub insert {
my $self = shift;
- my( $job, $offset, $mult ) = ( '', 0, 100);
- $job = shift if @_;
- $offset = shift if @_;
- $mult = shift if @_;
+ my $error;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -87,7 +82,7 @@ sub insert {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
- my $error = $self->check;
+ $error = $self->check;
return $error if $error;
#check for duplicates!
@@ -131,82 +126,48 @@ sub insert {
warn "WARNING: No duplicate checking done on merge of $svcdb exports";
}
- if ( @checks ) {
-
- my $done = 0;
- my $percheck = $mult / scalar(@checks);
-
- foreach my $check ( @checks ) {
-
- if ( $job ) {
- $error = $job->update_statustext(int( $offset + ($done+.33) *$percheck ));
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- my @current_svc = $self->part_export->svc_x;
- #warn "current: ". scalar(@current_svc). " $current_svc[0]\n";
-
- if ( $job ) {
- $error = $job->update_statustext(int( $offset + ($done+.67) *$percheck ));
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- my @new_svc = $self->part_svc->svc_x;
- #warn "new: ". scalar(@new_svc). " $new_svc[0]\n";
-
- if ( $job ) {
- $error = $job->update_statustext(int( $offset + ($done+1) *$percheck ));
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- my $method = $check->{'method'};
- my %cur_svc = map { $_->$method() => $_ } @current_svc;
- my @dup_svc = grep { $cur_svc{$_->$method()} } @new_svc;
- #my @diff_customer = grep {
- # $_->cust_pkg->custnum != $cur_svc{$_->$method()}->cust_pkg->custnum
- # } @dup_svc;
-
-
-
- if ( @dup_svc ) { #aye, that's the rub
- #error out for now, eventually accept different options of adjustments
- # to make to allow us to continue forward
- $dbh->rollback if $oldAutoCommit;
-
- my @diff_customer_svc = grep {
- my $cust_pkg = $_->cust_svc->cust_pkg;
- my $custnum = $cust_pkg ? $cust_pkg->custnum : 0;
- my $other_cust_pkg = $cur_svc{$_->$method()}->cust_svc->cust_pkg;
- my $other_custnum = $other_cust_pkg ? $other_cust_pkg->custnum : 0;
- $custnum != $other_custnum;
- } @dup_svc;
-
- my $label = $check->{'label'};
- my $sortby = $check->{'sortby'};
- return "Can't export ".
- $self->part_svc->svcpart.':'.$self->part_svc->svc. " service to ".
- $self->part_export->exportnum.':'.$self->part_export->exporttype.
- ' on '. $self->part_export->machine.
- ' : '. scalar(@dup_svc). " duplicate $label".
- ' ('. scalar(@diff_customer_svc). " from different customers)".
- ": ". join(', ', sort $sortby map { $_->$method() } @dup_svc )
- #": ". join(', ', sort $sortby map { $_->$method() } @diff_customer_svc )
- ;
- }
-
- $done++;
+ foreach my $check ( @checks ) {
+ my @current_svc = $self->part_export->svc_x;
+ #warn "current: ". scalar(@current_svc). " $current_svc[0]\n";
+ my @new_svc = $self->part_svc->svc_x;
+ #warn "new: ". scalar(@new_svc). " $new_svc[0]\n";
+ my $method = $check->{'method'};
+ my %cur_svc = map { $_->$method() => $_ } @current_svc;
+ my @dup_svc = grep { $cur_svc{$_->$method()} } @new_svc;
+ #my @diff_customer = grep {
+ # $_->cust_pkg->custnum != $cur_svc{$_->$method()}->cust_pkg->custnum
+ # } @dup_svc;
+
+
+
+ if ( @dup_svc ) { #aye, that's the rub
+ #error out for now, eventually accept different options of adjustments
+ # to make to allow us to continue forward
+ $dbh->rollback if $oldAutoCommit;
+
+ my @diff_customer_svc = grep {
+ my $cust_pkg = $_->cust_svc->cust_pkg;
+ my $custnum = $cust_pkg ? $cust_pkg->custnum : 0;
+ my $other_cust_pkg = $cur_svc{$_->$method()}->cust_svc->cust_pkg;
+ my $other_custnum = $other_cust_pkg ? $other_cust_pkg->custnum : 0;
+ $custnum != $other_custnum;
+ } @dup_svc;
+
+ my $label = $check->{'label'};
+ my $sortby = $check->{'sortby'};
+ return "Can't export ".
+ $self->part_svc->svcpart.':'.$self->part_svc->svc. " service to ".
+ $self->part_export->exportnum.':'.$self->part_export->exporttype.
+ ' on '. $self->part_export->machine.
+ ' : '. scalar(@dup_svc). " duplicate $label".
+ ' ('. scalar(@diff_customer_svc). " from different customers)".
+ #": ". join(', ', sort $sortby map { $_->$method() } @dup_svc )
+ ": ". join(', ', sort $sortby map { $_->$method() } @diff_customer_svc )
+ ;
}
+ }
- } #end of duplicate check, whew
+ #end of duplicate check, whew
$error = $self->SUPER::insert;
if ( $error ) {
diff --git a/FS/FS/h_Common.pm b/FS/FS/h_Common.pm
index d55da8cfb..58ead88e4 100644
--- a/FS/FS/h_Common.pm
+++ b/FS/FS/h_Common.pm
@@ -2,7 +2,6 @@ package FS::h_Common;
use strict;
use FS::Record qw(dbdef);
-use Carp qw(confess);
=head1 NAME
@@ -40,13 +39,8 @@ sub sql_h_search {
my( $self, $end ) = ( shift, shift );
my $table = $self->table;
- my $real_table = ($table =~ /^h_(.*)$/) ? $1 : $table;
- my $pkey = dbdef->table($real_table)->primary_key
- or die "can't (yet) search history table $real_table without a primary key";
-
- unless ($end) {
- confess 'Called sql_h_search without END_TIMESTAMP';
- }
+ my $pkey = dbdef->table($table)->primary_key
+ or die "can't (yet) search history table $table without a primary key";
my $notcancelled = '';
if ( scalar(@_) && $_[0] ) {
@@ -70,25 +64,11 @@ sub sql_h_search {
'',
- 'AS maintable',
+ 'maintable',
);
}
-=item sql_h_searchs END_TIMESTAMP [ START_TIMESTAMP ]
-
-Like sql_h_search, but limited to the single most recent record (before
-END_TIMESTAMP)
-
-=cut
-
-sub sql_h_searchs {
- my $self = shift;
- my($select, $where, $cacheobj, $as) = $self->sql_h_search(@_);
- $where .= ' LIMIT 1';
- ($select, $where, $cacheobj, $as);
-}
-
=back
=head1 BUGS
diff --git a/FS/FS/h_cust_svc.pm b/FS/FS/h_cust_svc.pm
index af0bf6064..9ef60fdc2 100644
--- a/FS/FS/h_cust_svc.pm
+++ b/FS/FS/h_cust_svc.pm
@@ -40,25 +40,9 @@ Returns a list consisting of:
sub label {
my $self = shift;
carp "FS::h_cust_svc::label called on $self" if $DEBUG;
- my $svc_x = $self->h_svc_x(@_);
- my $part_svc = $self->part_svc;
-
- unless ($svc_x) {
- carp "can't find h_". $self->part_svc->svcdb. '.svcnum '. $self->svcnum if $DEBUG;
- return $part_svc->svc, 'n/a', $part_svc->svcdb;
- }
-
- my @label;
- eval { @label = $self->_svc_label($svc_x, @_); };
-
- if ($@) {
- carp 'while resolving history record for svcdb/svcnum ' .
- $part_svc->svcdb . '/' . $self->svcnum . ': ' . $@ if $DEBUG;
- return $part_svc->svc, 'n/a', $part_svc->svcdb;
- } else {
- return @label;
- }
-
+ my $svc_x = $self->h_svc_x(@_)
+ or die "can't find h_". $self->part_svc->svcdb. '.svcnum '. $self->svcnum;
+ $self->_svc_label($svc_x, @_);
}
=item h_svc_x END_TIMESTAMP [ START_TIMESTAMP ]
@@ -73,23 +57,16 @@ cancelled before START_TIMESTAMP.
sub h_svc_x {
my $self = shift;
my $svcdb = $self->part_svc->svcdb;
-
- warn "requiring FS/h_$svcdb.pm" if $DEBUG;
- require "FS/h_$svcdb.pm";
- my $svc_x = qsearchs(
- "h_$svcdb",
- { 'svcnum' => $self->svcnum, },
- "FS::h_$svcdb"->sql_h_searchs(@_),
- ) || $self->SUPER::svc_x;
-
- if ($svc_x) {
- carp "Using $svcdb in place of missing h_${svcdb} record."
- if ($svc_x->isa('FS::' . $svcdb) and $DEBUG);
- return $svc_x;
- } else {
- return '';
- }
-
+ #if ( $svcdb eq 'svc_acct' && $self->{'_svc_acct'} ) {
+ # $self->{'_svc_acct'};
+ #} else {
+ warn "requiring FS/h_$svcdb.pm" if $DEBUG;
+ require "FS/h_$svcdb.pm";
+ qsearchs( "h_$svcdb",
+ { 'svcnum' => $self->svcnum, },
+ "FS::h_$svcdb"->sql_h_search(@_),
+ );
+ #}
}
=back
diff --git a/FS/FS/h_domain_record.pm b/FS/FS/h_domain_record.pm
deleted file mode 100644
index 0ab974fe2..000000000
--- a/FS/FS/h_domain_record.pm
+++ /dev/null
@@ -1,33 +0,0 @@
-package FS::h_domain_record;
-
-use strict;
-use vars qw( @ISA );
-use FS::h_Common;
-use FS::domain_record;
-
-@ISA = qw( FS::h_Common FS::domain_record );
-
-sub table { 'h_domain_record' };
-
-=head1 NAME
-
-FS::h_domain_record - Historical DNS entry objects
-
-=head1 SYNOPSIS
-
-=head1 DESCRIPTION
-
-An FS::h_domain_record object represents a historical entry in a DNS zone.
-FS::h_domain_record inherits from FS::h_Common and FS::domain_record.
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::h_Common>, L<FS::svc_external>, L<FS::Record>, schema.html from the base
-documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/h_svc_acct.pm b/FS/FS/h_svc_acct.pm
index 247d20c9a..cd98dd40e 100644
--- a/FS/FS/h_svc_acct.pm
+++ b/FS/FS/h_svc_acct.pm
@@ -1,18 +1,14 @@
package FS::h_svc_acct;
use strict;
-use vars qw( @ISA $DEBUG );
-use Carp qw(carp);
+use vars qw( @ISA );
use FS::Record qw(qsearchs);
use FS::h_Common;
use FS::svc_acct;
-use FS::svc_domain;
use FS::h_svc_domain;
@ISA = qw( FS::h_Common FS::svc_acct );
-$DEBUG = 0;
-
sub table { 'h_svc_acct' };
=head1 NAME
@@ -33,31 +29,10 @@ sub svc_domain {
my $self = shift;
qsearchs( 'h_svc_domain',
{ 'svcnum' => $self->domsvc },
- FS::h_svc_domain->sql_h_searchs(@_),
+ FS::h_svc_domain->sql_h_search(@_),
);
}
-=item domain
-
-Returns the domain associated with this account.
-
-=cut
-
-sub domain {
- my $self = shift;
- die "svc_acct.domsvc is null for svcnum ". $self->svcnum unless $self->domsvc;
-
- my $svc_domain = $self->svc_domain(@_) || $self->SUPER::svc_domain()
- or die 'no history svc_domain.svcnum for svc_acct.domsvc ' . $self->domsvc;
-
- carp 'Using FS::svc_acct record in place of missing FS::h_svc_acct record.'
- if ($svc_domain->isa('FS::svc_acct') and $DEBUG);
-
- $svc_domain->domain;
-
-}
-
-
=back
=head1 DESCRIPTION
diff --git a/FS/FS/h_svc_forward.pm b/FS/FS/h_svc_forward.pm
index 25b203904..231f9dfae 100644
--- a/FS/FS/h_svc_forward.pm
+++ b/FS/FS/h_svc_forward.pm
@@ -1,17 +1,12 @@
package FS::h_svc_forward;
use strict;
-use vars qw( @ISA $DEBUG );
-use FS::Record qw(qsearchs);
+use vars qw( @ISA );
+se FS::Record qw(qsearchs);
use FS::h_Common;
use FS::svc_forward;
-use FS::svc_acct;
use FS::h_svc_acct;
-use Carp qw(carp);
-
-$DEBUG = 0;
-
@ISA = qw( FS::h_Common FS::svc_forward );
sub table { 'h_svc_forward' };
@@ -32,18 +27,10 @@ FS::h_svc_forward - Historical mail forwarding alias objects
sub srcsvc_acct {
my $self = shift;
- my $h_svc_acct = qsearchs(
- 'h_svc_acct',
- { 'svcnum' => $self->srcsvc },
- FS::h_svc_acct->sql_h_searchs(@_),
- ) || $self->SUPER::srcsvc_acct
- or die "no history svc_acct.svcnum for svc_forward.srcsvc ". $self->srcsvc;
-
- carp 'Using svc_acct in place of missing h_svc_acct record.'
- if ($h_svc_acct->isa('FS::domain_record') and $DEBUG);
-
- return $h_svc_acct;
-
+ qsearchs( 'h_svc_acct',
+ { 'svcnum' => $self->srcsvc },
+ FS::h_svc_acct->sql_h_search(@_),
+ );
}
=item dstsvc_acct
@@ -52,17 +39,10 @@ sub srcsvc_acct {
sub dstsvc_acct {
my $self = shift;
- my $h_svc_acct = qsearchs(
- 'h_svc_acct',
- { 'svcnum' => $self->dstsvc },
- FS::h_svc_acct->sql_h_searchs(@_),
- ) || $self->SUPER::dstsvc_acct
- or die "no history svc_acct.svcnum for svc_forward.dstsvc ". $self->dstsvc;
-
- carp 'Using svc_acct in place of missing h_svc_acct record.'
- if ($h_svc_acct->isa('FS::domain_record') and $DEBUG);
-
- return $h_svc_acct;
+ qsearchs( 'h_svc_acct',
+ { 'svcnum' => $self->dstsvc },
+ FS::h_svc_acct->sql_h_search(@_),
+ );
}
=back
diff --git a/FS/FS/h_svc_www.pm b/FS/FS/h_svc_www.pm
index 2a3b6dca6..f2f8af820 100644
--- a/FS/FS/h_svc_www.pm
+++ b/FS/FS/h_svc_www.pm
@@ -1,17 +1,14 @@
package FS::h_svc_www;
use strict;
-use vars qw( @ISA $DEBUG );
-use Carp qw(carp);
-use FS::Record qw(qsearchs);
+use vars qw( @ISA );
+se FS::Record qw(qsearchs);
use FS::h_Common;
use FS::svc_www;
use FS::h_domain_record;
@ISA = qw( FS::h_Common FS::svc_www );
-$DEBUG = 0;
-
sub table { 'h_svc_www' };
=head1 NAME
@@ -30,21 +27,10 @@ FS::h_svc_www - Historical web virtual host objects
sub domain_record {
my $self = shift;
-
- carp 'Called FS::h_svc_www->domain_record on svcnum ' . $self->svcnum if $DEBUG;
-
- my $domain_record = qsearchs(
- 'h_domain_record',
- { 'recnum' => $self->recnum },
- FS::h_domain_record->sql_h_searchs(@_),
- ) || $self->SUPER::domain_record
- or die "no history domain_record.recnum for svc_www.recnum ". $self->domsvc;
-
- carp 'Using domain_record in place of missing h_domain_record record.'
- if ($domain_record->isa('FS::domain_record') and $DEBUG);
-
- return $domain_record;
-
+ qsearchs( 'h_domain_record',
+ { 'recnum' => $self->recnum },
+ FS::h_domain_record->sql_h_search(@_),
+ );
}
=back
diff --git a/FS/FS/option_Common.pm b/FS/FS/option_Common.pm
deleted file mode 100644
index f258fa1d6..000000000
--- a/FS/FS/option_Common.pm
+++ /dev/null
@@ -1,295 +0,0 @@
-package FS::option_Common;
-
-use strict;
-use vars qw( @ISA $DEBUG );
-use FS::Record qw( qsearch qsearchs dbh );
-
-@ISA = qw( FS::Record );
-
-$DEBUG = 0;
-
-=head1 NAME
-
-FS::option_Common - Base class for option sub-classes
-
-=head1 SYNOPSIS
-
-use FS::option_Common;
-
-@ISA = qw( FS::option_Common );
-
-=head1 DESCRIPTION
-
-FS::option_Common is intended as a base class for classes which have a
-simple one-to-many class associated with them, used to store a hash-like data
-structure of keys and values.
-
-=head1 METHODS
-
-=over 4
-
-=item insert [ HASHREF | OPTION => VALUE ... ]
-
-Adds this record to the database. If there is an error, returns the error,
-otherwise returns false.
-
-If a list or hash reference of options is supplied, option records are also
-created.
-
-=cut
-
-#false laziness w/queue.pm
-sub insert {
- my $self = shift;
- my $options =
- ( ref($_[0]) eq 'HASH' )
- ? shift
- : { @_ };
- warn "FS::option_Common::insert called on $self with options ".
- join(', ', map "$_ => ".$options->{$_}, keys %$options)
- if $DEBUG;
-
- 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 $error = $self->SUPER::insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- my $pkey = $self->pkey;
- my $option_table = $self->option_table;
-
- foreach my $optionname ( keys %{$options} ) {
- my $href = {
- $pkey => $self->get($pkey),
- 'optionname' => $optionname,
- 'optionvalue' => $options->{$optionname},
- };
-
- #my $option_record = eval "new FS::$option_table \$href";
- #if ( $@ ) {
- # $dbh->rollback if $oldAutoCommit;
- # return $@;
- #}
- my $option_record = "FS::$option_table"->new($href);
-
- $error = $option_record->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- '';
-
-}
-
-=item delete
-
-Delete this record from the database. Any associated option records are also
-deleted.
-
-=cut
-
-#foreign keys would make this much less tedious... grr dumb mysql
-sub delete {
- 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;
-
- my $error = $self->SUPER::delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- my $pkey = $self->pkey;
- #my $option_table = $self->option_table;
-
- foreach my $obj ( $self->option_objects ) {
- my $error = $obj->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- '';
-
-}
-
-=item replace [ HASHREF | OPTION => VALUE ... ]
-
-Replaces the OLD_RECORD with this one in the database. If there is an error,
-returns the error, otherwise returns false.
-
-If a list hash reference of options is supplied, part_export_option records are
-created or modified (see L<FS::part_export_option>).
-
-=cut
-
-sub replace {
- my $self = shift;
- my $old = shift;
- my $options =
- ( ref($_[0]) eq 'HASH' )
- ? shift
- : { @_ };
- warn "FS::option_Common::insert called on $self with options ".
- join(', ', map "$_ => ". $options->{$_}, keys %$options)
- if $DEBUG;
-
- 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 $error = $self->SUPER::replace($old);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- my $pkey = $self->pkey;
- my $option_table = $self->option_table;
-
- foreach my $optionname ( keys %{$options} ) {
- my $old = qsearchs( $option_table, {
- $pkey => $self->get($pkey),
- 'optionname' => $optionname,
- } );
-
- my $href = {
- $pkey => $self->get($pkey),
- 'optionname' => $optionname,
- 'optionvalue' => $options->{$optionname},
- };
-
- #my $new = eval "new FS::$option_table \$href";
- #if ( $@ ) {
- # $dbh->rollback if $oldAutoCommit;
- # return $@;
- #}
- my $new = "FS::$option_table"->new($href);
-
- $new->optionnum($old->optionnum) if $old;
- my $error = $old ? $new->replace($old) : $new->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- #remove extraneous old options
- foreach my $opt (
- grep { !exists $options->{$_->optionname} } $old->option_objects
- ) {
- my $error = $opt->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- '';
-
-}
-
-=item option_objects
-
-Returns all options as FS::I<tablename>_option objects.
-
-=cut
-
-sub option_objects {
- my $self = shift;
- my $pkey = $self->pkey;
- my $option_table = $self->option_table;
- qsearch($option_table, { $pkey => $self->get($pkey) } );
-}
-
-=item options
-
-Returns a list of option names and values suitable for assigning to a hash.
-
-=cut
-
-sub options {
- my $self = shift;
- map { $_->optionname => $_->optionvalue } $self->option_objects;
-}
-
-=item option OPTIONNAME
-
-Returns the option value for the given name, or the empty string.
-
-=cut
-
-sub option {
- my $self = shift;
- my $pkey = $self->pkey;
- my $option_table = $self->option_table;
- my $obj =
- qsearchs($option_table, {
- $pkey => $self->get($pkey),
- optionname => shift,
- } );
- $obj ? $obj->optionvalue : '';
-}
-
-
-sub pkey {
- my $self = shift;
- my $pkey = $self->dbdef_table->primary_key;
-}
-
-sub option_table {
- my $self = shift;
- my $option_table = $self->table . '_option';
- eval "use FS::$option_table";
- die $@ if $@;
- $option_table;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::Record>
-
-=cut
-
-1;
-
diff --git a/FS/FS/part_bill_event.pm b/FS/FS/part_bill_event.pm
index 8143e3473..7dfea5066 100644
--- a/FS/FS/part_bill_event.pm
+++ b/FS/FS/part_bill_event.pm
@@ -126,7 +126,7 @@ sub check {
or $c =~ /^\s*\$cust_bill\->(comp|realtime_(card|ach|lec)|batch_card|send)\(\);\s*$/
- or $c =~ /^\s*\$cust_bill\->send(_if_newest)?\(\'[\w\-\s]+\'\s*(,\s*(\d+|\[\s*\d+(,\s*\d+)*\s*\])\s*,\s*'[\w\@\.\-\+]*'\s*)?\);\s*$/
+ or $c =~ /^\s*\$cust_bill\->send(_if_newest)?\(\'[\w\-\s]+\'\s*(,\s*\d+\s*,\s*'[\w\@\.\-\+]*'\s*)?\);\s*$/
or $c =~ /^\s*\$cust_main\->apply_payments; \$cust_main->apply_credits; "";\s*$/
@@ -134,8 +134,6 @@ sub check {
or $c =~ /^\s*\$cust_main\->suspend_(if|unless)_pkgpart\([\d\,\s]*\);\s*$/
- or $c =~ /^\s*\$cust_bill\->cust_suspend_if_balance_over\([\d\.\s]*\);\s*$/
-
or do {
#log
return "illegal eventcode: $c";
@@ -160,12 +158,7 @@ sub check {
if ( $self->plandata =~ /^(agent_)?templatename\s+(.*)$/m ) {
my $name= $2;
- foreach my $file (qw( template
- latex latexnotes latexreturnaddress latexfooter
- latexsmallfooter
- html htmlnotes htmlreturnaddress htmlfooter
- ))
- {
+ foreach my $file (qw( template latex latexnotes )) {
unless ( $conf->exists("invoice_${file}_$name") ) {
$conf->set(
"invoice_${file}_$name" =>
@@ -178,32 +171,11 @@ sub check {
$self->SUPER::check;
}
-=item templatename
-
-Returns the alternate invoice template name, if any, or false if there is
-no alternate template for this invoice event.
-
-=cut
-
-sub templatename {
- my $self = shift;
- if ( $self->plan =~ /^send_(alternate|agent)$/
- && $self->plandata =~ /^(agent_)?templatename (.*)$/m
- )
- {
- $2;
- } else {
- '';
- }
-}
-
-
=back
=head1 BUGS
-The whole "eventcode" idea is bunk. This should be refactored with subclasses
-like part_pkg/ and part_export/
+Alas.
=head1 SEE ALSO
diff --git a/FS/FS/part_export.pm b/FS/FS/part_export.pm
index dce2d2a44..3f677b267 100644
--- a/FS/FS/part_export.pm
+++ b/FS/FS/part_export.pm
@@ -5,12 +5,11 @@ use vars qw( @ISA @EXPORT_OK $DEBUG %exports );
use Exporter;
use Tie::IxHash;
use FS::Record qw( qsearch qsearchs dbh );
-use FS::option_Common;
use FS::part_svc;
use FS::part_export_option;
use FS::export_svc;
-@ISA = qw( FS::option_Common );
+@ISA = qw(FS::Record);
@EXPORT_OK = qw(export_info);
$DEBUG = 0;
@@ -104,6 +103,48 @@ otherwise returns false.
If a hash reference of options is supplied, part_export_option records are
created (see L<FS::part_export_option>).
+=cut
+
+#false laziness w/queue.pm
+sub insert {
+ my $self = shift;
+ my $options = 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;
+
+ my $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ foreach my $optionname ( keys %{$options} ) {
+ my $part_export_option = new FS::part_export_option ( {
+ 'exportnum' => $self->exportnum,
+ 'optionname' => $optionname,
+ 'optionvalue' => $options->{$optionname},
+ } );
+ $error = $part_export_option->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
+}
+
=item delete
Delete this record from the database.
@@ -130,6 +171,14 @@ sub delete {
return $error;
}
+ foreach my $part_export_option ( $self->part_export_option ) {
+ my $error = $part_export_option->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
foreach my $export_svc ( $self->export_svc ) {
my $error = $export_svc->delete;
if ( $error ) {
@@ -144,6 +193,72 @@ sub delete {
}
+=item replace OLD_RECORD HASHREF
+
+Replaces the OLD_RECORD with this one in the database. If there is an error,
+returns the error, otherwise returns false.
+
+If a hash reference of options is supplied, part_export_option records are
+created or modified (see L<FS::part_export_option>).
+
+=cut
+
+sub replace {
+ my $self = shift;
+ my $old = shift;
+ my $options = 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;
+
+ my $error = $self->SUPER::replace($old);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ foreach my $optionname ( keys %{$options} ) {
+ my $old = qsearchs( 'part_export_option', {
+ 'exportnum' => $self->exportnum,
+ 'optionname' => $optionname,
+ } );
+ my $new = new FS::part_export_option ( {
+ 'exportnum' => $self->exportnum,
+ 'optionname' => $optionname,
+ 'optionvalue' => $options->{$optionname},
+ } );
+ $new->optionnum($old->optionnum) if $old;
+ my $error = $old ? $new->replace($old) : $new->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ #remove extraneous old options
+ foreach my $opt (
+ grep { !exists $options->{$_->optionname} } $old->part_export_option
+ ) {
+ my $error = $opt->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
+};
+
=item check
Checks all fields to make sure this is a valid export. If there is
@@ -232,17 +347,36 @@ L<FS::part_export_option>).
sub part_export_option {
my $self = shift;
- $self->option_objects;
+ qsearch('part_export_option', { 'exportnum' => $self->exportnum } );
}
=item options
Returns a list of option names and values suitable for assigning to a hash.
+=cut
+
+sub options {
+ my $self = shift;
+ map { $_->optionname => $_->optionvalue } $self->part_export_option;
+}
+
=item option OPTIONNAME
Returns the option value for the given name, or the empty string.
+=cut
+
+sub option {
+ my $self = shift;
+ my $part_export_option =
+ qsearchs('part_export_option', {
+ exportnum => $self->exportnum,
+ optionname => shift,
+ } );
+ $part_export_option ? $part_export_option->optionvalue : '';
+}
+
=item _rebless
Reblesses the object into the FS::part_export::EXPORTTYPE class, where
diff --git a/FS/FS/part_export/acct_sql.pm b/FS/FS/part_export/acct_sql.pm
index 4b92e80f1..fb0299c52 100644
--- a/FS/FS/part_export/acct_sql.pm
+++ b/FS/FS/part_export/acct_sql.pm
@@ -1,6 +1,6 @@
package FS::part_export::acct_sql;
-use vars qw(@ISA %info);
+use vars qw(@ISA %info @saltset);
use Tie::IxHash;
#use Digest::MD5 qw(md5_hex);
use FS::Record; #qw(qsearchs);
@@ -18,24 +18,7 @@ tie my %options, 'Tie::IxHash',
type => 'textarea',
},
'primary_key' => { label => 'Database primary key' },
- 'crypt' => { label => 'Password encryption',
- type=>'select', options=>[qw(crypt md5)],
- default=>'crypt',
- },
-;
-
-tie my %vpopmail_map, 'Tie::IxHash',
- 'pw_name' => 'username',
- 'pw_domain' => 'domain',
- 'pw_passwd' => 'crypt_password',
- 'pw_uid' => 'uid',
- 'pw_gid' => 'gid',
- 'pw_gecos' => 'finger',
- 'pw_dir' => 'dir',
- #'pw_shell' => 'shell',
- 'pw_shell' => 'quota',
;
-my $vpopmail_map = join('\n', map "$_ $vpopmail_map{$_}", keys %vpopmail_map );
tie my %postfix_courierimap_mailbox_map, 'Tie::IxHash',
'username' => 'email',
@@ -63,27 +46,23 @@ my $postfix_courierimap_alias_map =
%info = (
'svc' => 'svc_acct',
'desc' => 'Real-time export of accounts to SQL databases '.
- '(vpopmail, Postfix+Courier IMAP, others?)',
+ '(Postfix+Courier IMAP, others?)',
'options' => \%options,
'nodomain' => '',
'notes' => <<END
-Export accounts (svc_acct records) to SQL databases. Currently has default
-configurations for vpopmail and Postfix+Courier IMAP but intended to be
-configurable for other schemas as well.
+Export accounts (svc_acct records) to SQL databases. Written for
+Postfix+Courier IMAP but intended to be generally useful for generic SQL
+exports, eventually.
-<BR><BR>In contrast to sqlmail, this is intended to export just svc_acct
-records only, rather than a single export for svc_acct, svc_forward and
-svc_domain records, to export in "default" database schemas rather than
-configure the MTA or POP/IMAP server for a Freeside-specific schema, and
-to be configured for different mail server setups.
+<BR><BR>In contrast to sqlmail, this is newer and less well tested, and
+currently less flexible. It is intended to export just svc_acct records only,
+rather than a single export for svc_acct, svc_forward and svc_domain records,
+to export in "default" formats rather than configure the MTA or POP/IMAP server
+for a Freeside-specific schema, and possibly to be configured for different
+mail server setups through some subclassing rather than options.
<BR><BR>Use these buttons for some useful presets:
<UL>
- <li><INPUT TYPE="button" VALUE="vpopmail" onClick='
- this.form.table.value = "vpopmail";
- this.form.schema.value = "$vpopmail_map";
- this.form.primary_key.value = "pw_name, pw_domain";
- '>
<LI><INPUT TYPE="button" VALUE="postfix_courierimap_mailbox" onClick='
this.form.table.value = "mailbox";
this.form.schema.value = "$postfix_courierimap_mailbox_map";
@@ -111,10 +90,7 @@ sub _export_insert {
my %map = $self->_map;
my %record = map { my $value = $map{$_};
- my @arg = ();
- push @arg, $self->option('crypt')
- if $value eq 'crypt_password' && $self->option('crypt');
- $_ => $svc_acct->$value(@arg);
+ $_ => $svc_acct->$value();
} keys %map;
my $err_or_queue =
@@ -134,30 +110,17 @@ sub _export_replace {
my($self, $new, $old) = (shift, shift, shift);
my %map = $self->_map;
-
- my @primary_key = ();
- if ( $self->option('primary_key') =~ /,/ ) {
- foreach my $key ( split(/\s*,\s*/, $self->option('primary_key') ) ) {
- my $keymap = $map{$key};
- push @primary_key, $old->$keymap();
- }
- } else {
- my $keymap = $map{$self->option('primary_key')};
- push @primary_key, $old->$keymap();
- }
+ my $keymap = $map{$self->option('primary_key')};
my %record = map { my $value = $map{$_};
- my @arg = ();
- push @arg, $self->option('crypt')
- if $value eq 'crypt_password' && $self->option('crypt');
- $_ => $new->$value(@arg);
+ $_ => $new->$value();
} keys %map;
my $err_or_queue = $self->acct_sql_queue(
$new->svcnum,
'replace',
$self->option('table'),
- $self->option('primary_key'), @primary_key,
+ $self->option('primary_key') => $old->$keymap(),
%record,
);
return $err_or_queue unless ref($err_or_queue);
@@ -166,26 +129,13 @@ sub _export_replace {
sub _export_delete {
my ( $self, $svc_acct ) = (shift, shift);
-
my %map = $self->_map;
-
- my %primary_key = ();
- if ( $self->option('primary_key') =~ /,/ ) {
- foreach my $key ( split(/\s*,\s*/, $self->option('primary_key') ) ) {
- my $keymap = $map{$key};
- $primary_key{ $key } = $svc_acct->$keymap();
- }
- } else {
- my $keymap = $map{$self->option('primary_key')};
- $primary_key{ $self->option('primary_key') } = $svc_acct->$keymap(),
- }
-
+ my $keymap = $map{$self->option('primary_key')};
my $err_or_queue = $self->acct_sql_queue(
$svc_acct->svcnum,
'delete',
$self->option('table'),
- %primary_key,
- #$self->option('primary_key') => $svc_acct->$keymap(),
+ $self->option('primary_key') => $svc_acct->$keymap(),
);
return $err_or_queue unless ref($err_or_queue);
'';
@@ -236,27 +186,14 @@ sub acct_sql_delete { #subroutine, not method
sub acct_sql_replace { #subroutine, not method
my $dbh = acct_sql_connect(shift, shift, shift);
-
- my( $table, $pkey ) = ( shift, shift );
-
- my %primary_key = ();
- if ( $pkey =~ /,/ ) {
- foreach my $key ( split(/\s*,\s*/, $pkey ) ) {
- $primary_key{$key} = shift;
- }
- } else {
- $primary_key{$pkey} = shift;
- }
-
- my %record = @_;
+ my( $table, $pkey, $old_pkey, %record ) = @_;
my $sth = $dbh->prepare(
- "UPDATE $table".
- ' SET '. join(', ', map "$_ = ?", keys %record ).
- ' WHERE '. join(' AND ', map "$_ = ?", keys %primary_key )
+ "UPDATE $table SET ". join(', ', map "$_ = ?", keys %record ).
+ "WHERE $pkey = ?"
) or die $dbh->errstr;
- $sth->execute( values(%record), values(%primary_key) );
+ $sth->execute( values(%record), $old_pkey );
$dbh->disconnect;
}
diff --git a/FS/FS/part_export/artera_turbo.pm b/FS/FS/part_export/artera_turbo.pm
index c006db9cd..af4c79052 100644
--- a/FS/FS/part_export/artera_turbo.pm
+++ b/FS/FS/part_export/artera_turbo.pm
@@ -25,9 +25,6 @@ tie my %options, 'Tie::IxHash',
'debug' => { 'label' => 'Enable debug logging',
'type' => 'checkbox',
},
- 'enable_edit' => { 'label' => 'Enable local editing of Artera serial numbers and key codes (note that the changes will NOT be exported to Artera)',
- 'type' => 'checkbox',
- },
;
%info = (
@@ -43,7 +40,7 @@ Reseller API. Requires installation of
<a href="http://search.cpan.org/dist/Net-Artera">Net::Artera</a>
from CPAN. You probably also want to:
<UL>
- <LI>In the configuration UI section: set the <B>svc_external-skip_manual</B> and <B>svc_external-display_type</B> configuration values.
+ <LI>In the configuraiton UI section: set the <B>svc_external-skip_manual</B> and <B>svc_external-display_type</B> configuration values.
<LI>In the message catalog: set <B>svc_external-id</B> to <I>Artera Serial Number</I> and set <B>svc_external-title</B> to <I>Artera Key Code</I>.
</UL>
END
@@ -103,8 +100,8 @@ sub _export_insert {
if ( $result->{'id'} == 1 ) {
my $new = new FS::svc_external { $svc_external->hash };
- $new->id(sprintf('%010d', $result->{'ASN'}));
- $new->title( substr('0000000000'.uc($result->{'AKC'}), -10) );
+ $new->id($result->{'ASN'});
+ $new->title($result->{'AKC'});
$new->replace($svc_external);
} else {
$result->{'message'} || 'No response from Artera';
@@ -113,7 +110,6 @@ sub _export_insert {
sub _export_replace {
my( $self, $new, $old ) = (shift, shift, shift);
- return '' if $self->option('enable_edit');
return "can't change serial number with Artera"
if $old->id != $new->id && $old->id;
return "can't change key code with Artera"
@@ -123,58 +119,36 @@ sub _export_replace {
sub _export_delete {
my( $self, $svc_external ) = (shift, shift);
- $self->queue_statusChange(17, $svc_external);
+ $self->statusChange(17, $svc_external);
}
sub _export_suspend {
my( $self, $svc_external ) = (shift, shift);
- $self->queue_statusChange(16, $svc_external);
+ $self->statusChange(16, $svc_external);
}
sub _export_unsuspend {
my( $self, $svc_external ) = (shift, shift);
- $self->queue_statusChange(15, $svc_external);
-}
-
-sub queue_statusChange {
- my( $self, $status, $svc_external ) = @_;
-
- my $queue = new FS::queue {
- 'svcnum' => $svc_external->svcnum,
- 'job' => 'FS::part_export::artera_turbo::statusChange',
- };
- $queue->insert(
- ( map { $self->option($_) }
- qw( rid username password production ) ),
- $status,
- $svc_external->id,
- $svc_external->title,
- $self->option('debug'),
- );
+ $self->statusChange(15, $svc_external);
}
sub statusChange {
- my( $rid, $username, $password, $prod, $status, $id, $title, $debug ) = @_;
+ my( $self, $status, $svc_external ) = @_;
eval "use Net::Artera;";
return $@ if $@;
- $Net::Artera::DEBUG = 1 if $debug;
-
- my $artera = new Net::Artera (
- 'rid' => $rid,
- 'username' => $username,
- 'password' => $password,
- 'production' => $prod,
- );
+ $Net::Artera::DEBUG = 1 if $self->option('debug');
+ my $artera = $self->_new_Artera;
my $result = $artera->statusChange(
- 'asn' => sprintf('%010d', $id),
- 'akc' => substr("0000000000$title", -10),
+ 'asn' => sprintf('%010d', $svc_external->id),
+ 'akc' => $svc_external->title,
'statusid' => $status,
);
- die $result->{'message'} unless $result->{'id'} == 1;
-
+ $result->{'id'} == 1
+ ? ''
+ : $result->{'message'};
}
1;
diff --git a/FS/FS/part_export/cp.pm b/FS/FS/part_export/cp.pm
index 96fa43710..a295c574b 100644
--- a/FS/FS/part_export/cp.pm
+++ b/FS/FS/part_export/cp.pm
@@ -43,9 +43,8 @@ sub _export_replace {
my( $self, $new, $old ) = (shift, shift, shift);
return "can't change domain with Critical Path"
if $old->domain ne $new->domain;
- return "can't change username with Critical Path" #CP no longer supports this
- if $old->username ne $new->username;
- return '' unless $old->_password ne $new->_password;
+ return '' unless $old->username ne $new->username
+ || $old->_password ne $new->_password;
$self->cp_queue( $new->svcnum, 'replace', $new->domain,
$old->username, $new->username, $old->_password, $new->_password );
}
diff --git a/FS/FS/part_export/cpanel.pm b/FS/FS/part_export/cpanel.pm
deleted file mode 100644
index 0ad00df01..000000000
--- a/FS/FS/part_export/cpanel.pm
+++ /dev/null
@@ -1,192 +0,0 @@
-package FS::part_export::cpanel;
-
-use vars qw(@ISA %info);
-use Tie::IxHash;
-use FS::part_export;
-
-@ISA = qw(FS::part_export);
-
-tie my %options, 'Tie::IxHash',
- 'user' => { label=>'Remote access username' },
- 'accesshash' => { label=>'Remote access key', type=>'textarea' },
- 'debug' => { label=>'Enable debugging', type=>'checkbox' },
-;
-
-%info = (
- 'svc' => 'svc_acct',
- 'desc' => 'Real-time export to Cpanel control panel.',
- 'options' => \%options,
- 'nodomain' => 'Y',
- 'notes' => 'Real time export to a the <a href="http://www.cpanel.net/">Cpanel</a> control panel software. Service definition names are exported as Cpanel packages. Requires installation of the Cpanel::Accounting perl module distributed with Cpanel.',
-);
-
-sub rebless { shift; }
-
-sub _export_insert {
- my($self, $svc_acct) = (shift, shift);
- $err_or_queue = $self->cpanel_queue( $svc_acct->svcnum, 'insert',
- $svc_acct->domain,
- $svc_acct->username,
- $svc_acct->_password,
- $svc_acct->cust_svc->part_svc->svc,
- );
- ref($err_or_queue) ? '' : $err_or_queue;
-}
-
-sub _export_replace {
- my( $self, $new, $old ) = (shift, shift, shift);
- return "can't change username with cpanel"
- if $old->username ne $new->username;
- return "can't change password with cpanel"
- if $old->_passsword ne $new->_password;
- return "can't change domain with cpanel"
- if $old->domain ne $new->domain;
-
- '';
-
- ##return '' unless $old->_password ne $new->_password;
- #$err_or_queue = $self->cpanel_queue( $new->svcnum,
- # 'replace', $new->username, $new->_password );
- #ref($err_or_queue) ? '' : $err_or_queue;
-}
-
-sub _export_delete {
- my( $self, $svc_acct ) = (shift, shift);
- $err_or_queue = $self->cpanel_queue( $svc_acct->svcnum,
- 'delete', $svc_acct->username
- );
- ref($err_or_queue) ? '' : $err_or_queue;
-}
-
-sub _export_suspend {
- my( $self, $svc_acct ) = (shift, shift);
- $err_or_queue = $self->cpanel_queue( $svc_acct->svcnum,
- 'suspend', $svc_acct->username );
- ref($err_or_queue) ? '' : $err_or_queue;
-}
-
-sub _export_unsuspend {
- my( $self, $svc_acct ) = (shift, shift);
- $err_or_queue = $self->cpanel_queue( $svc_acct->svcnum,
- 'unsuspend', $svc_acct->username );
- ref($err_or_queue) ? '' : $err_or_queue;
-}
-
-
-sub cpanel_queue {
- my( $self, $svcnum, $method ) = (shift, shift, shift);
- my $queue = new FS::queue {
- 'svcnum' => $svcnum,
- 'job' => "FS::part_export::cpanel::cpanel_$method",
- };
- $queue->insert(
- $self->machine,
- $self->option('user'),
- $self->option('accesshash'),
- $self->option('debug'),
- @_
- ) or $queue;
-}
-
-
-sub cpanel_insert { #subroutine, not method
- my( $machine, $user, $accesshash, $debug ) = splice(@_,0,4);
-
-# my $whm = cpanel_connect($machine, $user, $accesshash, $debug);
-# warn " cpanel->createacct ". join(', ', @_). "\n"
-# if $debug;
-# my $response = $whm->createacct(@_);
-# die $whm->{'error'} if $whm->{'error'};
-# warn " cpanel response: $response\n"
-# if $debug;
-
- warn "cpanel_insert: attempting web interface to add POP"
- if $debug;
-
- my($domain, $username, $password, $svc) = @_;
-
- use LWP::UserAgent;
- use HTTP::Request::Common qw(POST);
-
- my $url =
- "http://$user:$accesshash\@$domain:2082/frontend/x/mail/addpop2.html";
-
- my $ua = LWP::UserAgent->new();
-
- #$req->authorization_basic($user, $accesshash);
-
- my $res = $ua->request(
- POST( $url,
- [
- 'email' => $username,
- 'domain' => $domain,
- 'password' => $password,
- 'quota' => 10, #?
- ]
- )
- );
-
- die "Error submitting data to $url: ". $res->status_line
- unless $res->is_success;
-
- die "Username in use"
- if $res->content =~ /exists/;
-
- die "Account not created: ". $res->content
- if $res->content =~ /failure/;
-
-}
-
-#sub cpanel_replace { #subroutine, not method
-#}
-
-sub cpanel_delete { #subroutine, not method
- my( $machine, $user, $accesshash, $debug ) = splice(@_,0,4);
- my $whm = cpanel_connect($machine, $user, $accesshash, $debug);
- warn " cpanel->killacct ". join(', ', @_). "\n"
- if $debug;
- my $response = $whm->killacct(shift);
- die $whm->{'error'} if $whm->{'error'};
- warn " cpanel response: $response\n"
- if $debug;
-}
-
-sub cpanel_suspend { #subroutine, not method
- my( $machine, $user, $accesshash, $debug ) = splice(@_,0,4);
- my $whm = cpanel_connect($machine, $user, $accesshash, $debug);
- warn " cpanel->suspend ". join(', ', @_). "\n"
- if $debug;
- my $response = $whm->suspend(shift);
- die $whm->{'error'} if $whm->{'error'};
- warn " cpanel response: $response\n"
- if $debug;
-}
-
-sub cpanel_unsuspend { #subroutine, not method
- my( $machine, $user, $accesshash, $debug ) = splice(@_,0,4);
- my $whm = cpanel_connect($machine, $user, $accesshash, $debug);
- warn " cpanel->unsuspend ". join(', ', @_). "\n"
- if $debug;
- my $response = $whm->unsuspend(shift);
- die $whm->{'error'} if $whm->{'error'};
- warn " cpanel response: $response\n"
- if $debug;
-}
-
-sub cpanel_connect {
- my( $host, $user, $accesshash, $debug ) = @_;
-
- eval "use Cpanel::Accounting;";
- die $@ if $@;
-
- warn "creating new Cpanel::Accounting connection to $user@$host\n"
- if $debug;
-
- my $whm = new Cpanel::Accounting;
- $whm->{'host'} = $host;
- $whm->{'user'} = $user;
- $whm->{'accesshash'} = $accesshash;
- $whm->{'usessl'} = 1;
-
- $whm;
-}
diff --git a/FS/FS/part_export/domain_shellcommands.pm b/FS/FS/part_export/domain_shellcommands.pm
index d15f41a84..0ba561711 100644
--- a/FS/FS/part_export/domain_shellcommands.pm
+++ b/FS/FS/part_export/domain_shellcommands.pm
@@ -70,7 +70,6 @@ sub _export_delete {
sub _export_command {
my ( $self, $action, $svc_domain) = (shift, shift, shift);
my $command = $self->option($action);
- return '' if $command =~ /^\s*$/;
#set variable for the command
no strict 'vars';
diff --git a/FS/FS/part_export/everyone_net.pm b/FS/FS/part_export/everyone_net.pm
deleted file mode 100644
index e04318e10..000000000
--- a/FS/FS/part_export/everyone_net.pm
+++ /dev/null
@@ -1,132 +0,0 @@
-package FS::part_export::everyone_net;
-
-use vars qw(@ISA %info);
-use Tie::IxHash;
-use FS::part_export;
-
-@ISA = qw(FS::part_export);
-
-tie my %options, 'Tie::IxHash',
- 'clientID' => { label=>'clientID' },
- 'password' => { label=>'Password' },
- #'workgroup' => { label=>'Default Workgroup' },
- 'debug' => { label=>'Enable debugging',
- type=>'checkbox' },
-;
-
-%info = (
- 'svc' => 'svc_acct',
- 'desc' => 'Real-time export to Everyone.net outsourced mail service',
- 'options'=> \%options,
- 'notes' => <<'END'
-Real-time export to
-<a href="http://www.cp.net/">Everyone.net</a> via the XRC Remote API.
-Requires installation of
-<a href="http://search.cpan.org/dist/Net-XRC">Net::XRC</a>
-from CPAN.
-END
-);
-
-sub rebless { shift; }
-
-# experiement: want the status of these right away (don't want account to
-# create or whatever and then get error in the queue from dup username or
-# something), so no queueing
-
-sub _export_insert {
- my( $self, $svc_acct ) = (shift, shift);
-
- eval "use Net::XRC qw(:types);";
- return $@ if $@;
-
- $self->_xrc_command( 'createUser',
- $svc_acct->domain,
- [],
- string($svc_acct->username),
- string($svc_acct->_password),
- );
-}
-
-sub _xrc_command {
- my( $self, $method, $domain, @args ) = @_;
-
- eval "use Net::XRC qw(:types);";
- return $@ if $@;
-
- local($Net::XRC::DEBUG) = 1
- if $self->option('debug');
-
- my $xrc = new Net::XRC (
- 'clientID' => $self->option('clientID'),
- 'password' => $self->option('password'),
- );
-
- my $dresponse = $xrc->lookupMXReadyClientIDByEmailDomain( string($domain) );
- return $dresponse->error unless $dresponse->is_success;
- my $clientID = $dresponse->content;
- return "clientID for domain $domain not found"
- if $clientID == -1;
-
- my $response = $xrc->$method($clientID, @args);
- return $response->error unless $response->is_success;
- '';
-
-}
-
-sub _export_replace {
- my( $self, $new, $old ) = (shift, shift, shift);
-
- eval "use Net::XRC qw(:types);";
- return $@ if $@;
-
- return "can't change domain with Everyone.net"
- if $old->domain ne $new->domain;
- return "can't change username with Everyone.net"
- if $old->username ne $new->username;
- return '' unless $old->_password ne $new->_password;
-
- $self->_xrc_command( 'setUserPassword',
- $new->domain,
- string($new->username),
- string($new->_password),
- );
-}
-
-sub _export_delete {
- my( $self, $svc_acct ) = (shift, shift);
-
- eval "use Net::XRC qw(:types);";
- return $@ if $@;
-
- $self->_xrc_command( 'deleteUser',
- $svc_acct->domain,
- string($svc_acct->username),
- );
-}
-
-sub _export_suspend {
- my( $self, $svc_acct ) = (shift, shift);
-
- eval "use Net::XRC qw(:types);";
- return $@ if $@;
-
- $self->_xrc_command( 'suspendUser',
- $svc_acct->domain,
- string($svc_acct->username),
- );
-}
-
-sub _export_unsuspend {
- my( $self, $svc_acct ) = (shift, shift);
-
- eval "use Net::XRC qw(:types);";
- return $@ if $@;
-
- $self->_xrc_command( 'unsuspendUser',
- $svc_acct->domain,
- string($svc_acct->username),
- );
-}
-
-1;
-
diff --git a/FS/FS/part_export/forward_shellcommands.pm b/FS/FS/part_export/forward_shellcommands.pm
index cee24e452..fe304350c 100644
--- a/FS/FS/part_export/forward_shellcommands.pm
+++ b/FS/FS/part_export/forward_shellcommands.pm
@@ -45,9 +45,8 @@ Run remote commands via SSH, for forwards. You will need to
The following variables are available for interpolation (prefixed with
<code>new_</code> or <code>old_</code> for replace operations):
<UL>
- <LI><code>$username</code> - username of forward source
- <LI><code>$domain</code> - domain of forward source
- <LI><code>$source</code> - forward source ($username@$domain)
+ <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>
@@ -69,7 +68,6 @@ sub _export_delete {
sub _export_command {
my ( $self, $action, $svc_forward ) = (shift, shift, shift);
my $command = $self->option($action);
- return '' if $command =~ /^\s*$/;
#set variable for the command
no strict 'vars';
@@ -78,17 +76,10 @@ sub _export_command {
${$_} = $svc_forward->getfield($_) foreach $svc_forward->fields;
}
- if ( $svc_forward->srcsvc ) {
- my $srcsvc_acct = $svc_forward->srcsvc_acct;
- $username = $srcsvc_acct->username;
- $domain = $srcsvc_acct->domain;
- $source = $srcsvc_acct->email;
- } else {
- $source = $svc_forward->src;
- ( $username, $domain ) = split(/\@/, $source);
- }
-
- if ($svc_forward->dstsvc) {
+ my $svc_acct = $svc_forward->srcsvc_acct;
+ $username = $svc_acct->username;
+ $domain = $svc_acct->domain;
+ if ($svc_forward->dstsvc_acct) {
$destination = $svc_forward->dstsvc_acct->email;
} else {
$destination = $svc_forward->dst;
@@ -115,33 +106,19 @@ sub _export_replace {
${"new_$_"} = $new->getfield($_) foreach $new->fields;
}
- if ( $old->srcsvc ) {
- my $srcsvc_acct = $old->srcsvc_acct;
- $old_username = $srcsvc_acct->username;
- $old_domain = $srcsvc_acct->domain;
- $old_source = $srcsvc_acct->email;
- } else {
- $old_source = $old->src;
- ( $old_username, $old_domain ) = split(/\@/, $old_source);
- }
-
- if ( $old->dstsvc ) {
+ my $old_svc_acct = $old->srcsvc_acct;
+ $old_username = $old_svc_acct->username;
+ $old_domain = $old_svc_acct->domain;
+ if ($old->dstsvc_acct) {
$old_destination = $old->dstsvc_acct->email;
} else {
$old_destination = $old->dst;
}
- if ( $new->srcsvc ) {
- my $srcsvc_acct = $new->srcsvc_acct;
- $new_username = $srcsvc_acct->username;
- $new_domain = $srcsvc_acct->domain;
- $new_source = $srcsvc_acct->email;
- } else {
- $new_source = $new->src;
- ( $new_username, $new_domain ) = split(/\@/, $new_source);
- }
-
- if ( $new->dstsvc ) {
+ my $new_svc_acct = $new->srcsvc_acct;
+ $new_username = $new_svc_acct->username;
+ $new_domain = $new_svc_acct->domain;
+ if ($new->dstsvc) {
$new_destination = $new->dstsvc_acct->email;
} else {
$new_destination = $new->dst;
diff --git a/FS/FS/part_export/http.pm b/FS/FS/part_export/http.pm
index 55d832966..0be2a0f36 100644
--- a/FS/FS/part_export/http.pm
+++ b/FS/FS/part_export/http.pm
@@ -18,7 +18,7 @@ tie my %options, 'Tie::IxHash',
type => 'textarea',
default => join("\n",
'DomainName $svc_x->domain',
- 'Email ( grep { $_ !~ /^(POST|FAX)$/ } $svc_x->cust_svc->cust_pkg->cust_main->invoicing_list)[0]',
+ 'Email ( grep { $_ ne "POST" } $svc_x->cust_svc->cust_pkg->cust_main->invoicing_list)[0]',
'test 1',
'reseller $svc_x->cust_svc->cust_pkg->part_pkg->pkg =~ /reseller/i',
),
diff --git a/FS/FS/part_export/infostreet.pm b/FS/FS/part_export/infostreet.pm
index ef16c7c54..309e7ce6f 100644
--- a/FS/FS/part_export/infostreet.pm
+++ b/FS/FS/part_export/infostreet.pm
@@ -67,7 +67,7 @@ sub _export_insert {
$_ => $cust_main->getfield( $infostreet2cust_main{$_} );
} keys %infostreet2cust_main );
- my @emails = grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list;
+ my @emails = grep { $_ ne 'POST' } $cust_main->invoicing_list;
$contact_info{'email'} = $emails[0] if @emails;
#this one is kinda noment-specific
diff --git a/FS/FS/part_export/radiator.pm b/FS/FS/part_export/radiator.pm
deleted file mode 100644
index 2ac3edb22..000000000
--- a/FS/FS/part_export/radiator.pm
+++ /dev/null
@@ -1,167 +0,0 @@
-package FS::part_export::radiator;
-
-use vars qw(@ISA %info $radusers);
-use Tie::IxHash;
-use FS::part_export::sqlradius;
-
-tie my %options, 'Tie::IxHash', %FS::part_export::sqlradius::options;
-
-%info = (
- 'svc' => 'svc_acct',
- 'desc' => 'Real-time export to RADIATOR',
- 'options' => \%options,
- 'nodomain' => '',
- 'notes' => <<'END',
-Real-time export of the <b>radusers</b> table to any SQL database in
-<a href="http://www.open.com.au/radiator/">Radiator</a>-native format.
-To setup accounting, see the RADIATOR documentation for hooks to update
-a standard <b>radacct</b> table.
-END
-);
-
-@ISA = qw(FS::part_export::sqlradius); #for regular sqlradius accounting
-
-$radusers = 'RADUSERS'; #MySQL is case sensitive about table names! huh
-
-#sub export_username {
-# my($self, $svc_acct) = (shift, shift);
-# $svc_acct->email;
-#}
-
-sub _export_insert {
- my( $self, $svc_acct ) = (shift, shift);
-
- $self->radiator_queue(
- $svc_acct->svcnum,
- 'insert',
- $self->_radiator_hash($svc_acct),
- );
-}
-
-sub _export_replace {
- my( $self, $new, $old ) = (shift, shift, shift);
-
-# return "can't (yet) change domain with radiator export"
-# if $old->domain ne $new->domain;
-# return "can't (yet) change username with radiator export"
-# if $old->username ne $new->username;
-
- $self->radiator_queue(
- $new->svcnum,
- 'replace',
- $self->export_username($old),
- $self->_radiator_hash($new),
- );
-}
-
-sub _export_delete {
- my( $self, $svc_acct ) = (shift, shift);
-
- $self->radiator_queue(
- $svc_acct->svcnum,
- 'delete',
- $self->export_username($svc_acct),
- );
-}
-
-sub _radiator_hash {
- my( $self, $svc_acct ) = @_;
- my %hash = (
- 'username' => $self->export_username($svc_acct),
- 'pass_word' => $svc_acct->crypt_password,
- 'fullname' => $svc_acct->finger,
- map { my $method = "radius_$_"; $_ => $svc_acct->$method(); }
- qw( framed_filter_id framed_mtu framed_netmask framed_protocol
- framed_routing login_host login_service login_tcp_port )
- );
- $hash{'timeleft'} = $svc_acct->seconds
- if $svc_acct->seconds =~ /^\d+$/;
- $hash{'staticaddress'} = $svc_acct->slipip
- if $svc_acct->slipip =~ /^[\d\.]+$/; # and $self->slipip ne '0.0.0.0';
-
- $hash{'servicename'} = ( $svc_acct->radius_groups )[0];
-
- my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
- $hash{'validto'} = $cust_pkg->bill
- if $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill;
-
- #some other random stuff, should probably be attributes or virtual fields
- #$hash{'state'} = 0; #only inserts
- #$hash{'badlogins'} = 0; #only inserts
- $hash{'maxlogins'} = 1;
- $hash{'addeddate'} = $cust_pkg->setup
- if $cust_pkg && $cust_pkg->setup;
- $hash{'validfrom'} = $cust_pkg->last_bill || $cust_pkg->setup
- if $cust_pkg && ( $cust_pkg->last_bill || $cust_pkg->setup );
- $hash{'state'} = $cust_pkg->susp ? 1 : 0
- if $cust_pkg;
-
- %hash;
-}
-
-sub radiator_queue {
- my( $self, $svcnum, $method ) = (shift, shift, shift);
- my $queue = new FS::queue {
- 'svcnum' => $svcnum,
- 'job' => "FS::part_export::radiator::radiator_$method",
- };
- $queue->insert(
- $self->option('datasrc'),
- $self->option('username'),
- $self->option('password'),
- @_,
- ); # or $queue;
-}
-
-sub radiator_insert { #subroutine, not method
- my $dbh = radiator_connect(shift, shift, shift);
- my %hash = @_;
- $hash{'state'} = 0; #see "random stuff" above
- $hash{'badlogins'} = 0; #see "random stuff" above
-
- my $sth = $dbh->prepare(
- "INSERT INTO $radusers ( ". join(', ', keys %hash ). ' ) '.
- 'VALUES ( '. join(', ', map '?', keys %hash ). ' ) '
- ) or die $dbh->errstr;
- $sth->execute( values %hash )
- or die $sth->errstr;
-
- $dbh->disconnect;
-
-}
-
-sub radiator_replace { #subroutine, not method
- my $dbh = radiator_connect(shift, shift, shift);
- my ( $old_username, %hash ) = @_;
-
- my $sth = $dbh->prepare(
- "UPDATE $radusers SET ". join(', ', map " $_ = ?", keys %hash ).
- ' WHERE username = ?'
- ) or die $dbh->errstr;
- $sth->execute( values(%hash), $old_username )
- or die $sth->errstr;
-
- $dbh->disconnect;
-}
-
-sub radiator_delete { #subroutine, not method
- my $dbh = radiator_connect(shift, shift, shift);
- my ( $username ) = @_;
-
- my $sth = $dbh->prepare(
- "DELETE FROM $radusers WHERE username = ?"
- ) or die $dbh->errstr;
- $sth->execute( $username )
- or die $sth->errstr;
-
- $dbh->disconnect;
-}
-
-
-sub radiator_connect {
- #my($datasrc, $username, $password) = @_;
- #DBI->connect($datasrc, $username, $password) or die $DBI::errstr;
- DBI->connect(@_) or die $DBI::errstr;
-}
-
-1;
diff --git a/FS/FS/part_export/shellcommands.pm b/FS/FS/part_export/shellcommands.pm
index 646c5ff71..4f201cf9c 100644
--- a/FS/FS/part_export/shellcommands.pm
+++ b/FS/FS/part_export/shellcommands.pm
@@ -1,6 +1,6 @@
package FS::part_export::shellcommands;
-use vars qw(@ISA %info);
+use vars qw(@ISA %info @saltset);
use Tie::IxHash;
use String::ShellQuote;
use FS::part_export;
@@ -26,7 +26,7 @@ tie my %options, 'Tie::IxHash',
default=>'',
},
'usermod' => { label=>'Modify command',
- default=>'usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -g $new_gid -p $new_crypt_password $old_username',
+ default=>'usermod -c $new_finger -d $new_dir -m -l $new_username -s $new_shell -u $new_uid -p $new_crypt_password $old_username',
#default=>'[ -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; '.
@@ -38,12 +38,9 @@ tie my %options, 'Tie::IxHash',
type =>'textarea',
default=>'',
},
- 'usermod_pwonly' => { label=>'Disallow username, domain, uid, gid, and dir changes', #and RADIUS group changes',
+ 'usermod_pwonly' => { label=>'Disallow username changes',
type =>'checkbox',
},
- 'usermod_nousername' => { label=>'Disallow just username changes',
- type =>'checkbox',
- },
'suspend' => { label=>'Suspension command',
default=>'usermod -L $username',
},
@@ -56,10 +53,6 @@ tie my %options, 'Tie::IxHash',
'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
default=>'',
},
- 'crypt' => { label => 'Default password encryption',
- type=>'select', options=>[qw(crypt md5)],
- default => 'crypt',
- },
;
%info = (
@@ -82,7 +75,7 @@ running will not accept a domain as a parameter. You will need to
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 -g $new_gid -p $new_crypt_password $old_username";
+ 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="";
@@ -91,10 +84,10 @@ running will not accept a domain as a parameter. You will need to
'>
<LI>
<INPUT TYPE="button" VALUE="FreeBSD before 4.10 / 5.3" onClick='
- this.form.useradd.value = "lockf /etc/passwd.lock pw useradd $username -d $dir -m -s $shell -u $uid -c $finger -h 0";
+ 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 -g $new_gid -c $new_finger -h 0";
+ 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="";
@@ -112,7 +105,7 @@ running will not accept a domain as a parameter. You will need to
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 -g $new_gid -c $new_finger -h 0";
+ 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";
this.form.suspend.value = "pw lock $username";
this.form.suspend_stdin.value="";
@@ -125,7 +118,7 @@ running will not accept a domain as a parameter. You will need to
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 -g $new_gid -p $new_crypt_password $old_username";
+ 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="";
@@ -151,8 +144,8 @@ old_ for replace operations):
<UL>
<LI><code>$username</code>
<LI><code>$_password</code>
- <LI><code>$quoted_password</code> - unencrypted password, already quoted for the shell (do not add additional quotes)
- <LI><code>$crypt_password</code> - encrypted password, already quoted for the shell (do not add additional quotes)
+ <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)
@@ -167,6 +160,8 @@ old_ for replace operations):
END
);
+@saltset = ( 'a'..'z' , 'A'..'Z' , '0'..'9' , '.' , '/' );
+
sub rebless { shift; }
sub _export_insert {
@@ -221,7 +216,7 @@ sub _export_command {
my $cust_pkg = $svc_acct->cust_svc->cust_pkg;
if ( $cust_pkg ) {
- $email = ( grep { $_ !~ /^(POST|FAX)$/ } $cust_pkg->cust_main->invoicing_list )[0];
+ $email = ( grep { $_ ne 'POST' } $cust_pkg->cust_main->invoicing_list )[0];
} else {
$email = '';
}
@@ -234,8 +229,16 @@ sub _export_command {
$quoted_password = shell_quote $_password;
$domain = $svc_acct->domain;
- $crypt_password =
- shell_quote( $svc_acct->crypt_password( $self->option('crypt') ) );
+ #eventually should check a "password-encoding" field
+ if ( length($svc_acct->_password) == 13
+ || $svc_acct->_password =~ /^\$(1|2a?)\$/ ) {
+ $crypt_password = shell_quote $svc_acct->_password;
+ } else {
+ $crypt_password = crypt(
+ $svc_acct->_password,
+ $saltset[int(rand(64))].$saltset[int(rand(64))]
+ );
+ }
@radius_groups = $svc_acct->radius_groups;
@@ -267,39 +270,40 @@ sub _export_replace {
$old_domain = $old->domain;
$new_domain = $new->domain;
- $new_crypt_password =
- shell_quote( $new->crypt_password( $self->option('crypt') ) );
+ #eventuall should check a "password-encoding" field
+ if ( length($new->_password) == 13
+ || $new->_password =~ /^\$(1|2a?)\$/ ) {
+ $new_crypt_password = shell_quote $new->_password;
+ } else {
+ $new_crypt_password =
+ crypt( $new->_password, $saltset[int(rand(64))].$saltset[int(rand(64))]
+ );
+ }
@old_radius_groups = $old->radius_groups;
@new_radius_groups = $new->radius_groups;
- my $error = '';
- if ( $self->option('usermod_pwonly') || $self->option('usermod_nousername') ){
+ if ( $self->option('usermod_pwonly') ) {
+ my $error = '';
if ( $old_username ne $new_username ) {
$error ||= "can't change username";
}
- }
- if ( $self->option('usermod_pwonly') ) {
if ( $old_domain ne $new_domain ) {
$error ||= "can't change domain";
}
if ( $old_uid != $new_uid ) {
$error ||= "can't change uid";
}
- if ( $old_gid != $new_gid ) {
- $error ||= "can't change gid";
- }
if ( $old_dir ne $new_dir ) {
$error ||= "can't change dir";
}
- #if ( join("\n", sort @old_radius_groups) ne
- # join("\n", sort @new_radius_groups) ) {
- # $error ||= "can't change RADIUS groups";
- #}
+ if ( join("\n", sort @old_radius_groups) ne
+ join("\n", sort @new_radius_groups) ) {
+ $error ||= "can't change RADIUS groups";
+ }
+ return $error. ' ('. $self->exporttype. ' to '. $self->machine. ')'
+ if $error;
}
- return $error. ' ('. $self->exporttype. ' to '. $self->machine. ')'
- if $error;
-
$self->shellcommands_queue( $new->svcnum,
user => $self->option('user')||'root',
host => $self->machine,
diff --git a/FS/FS/part_export/shellcommands_withdomain.pm b/FS/FS/part_export/shellcommands_withdomain.pm
index 7c5d9045f..89ee95fa3 100644
--- a/FS/FS/part_export/shellcommands_withdomain.pm
+++ b/FS/FS/part_export/shellcommands_withdomain.pm
@@ -29,12 +29,9 @@ tie my %options, 'Tie::IxHash',
type =>'textarea',
#default=>"$_password\n$_password\n",
},
- 'usermod_pwonly' => { label=>'Disallow username, domain, uid, dir and RADIUS group changes',
+ 'usermod_pwonly' => { label=>'Disallow username changes',
type =>'checkbox',
},
- 'usermod_nousername' => { label=>'Disallow just username changes',
- type =>'checkbox',
- },
'suspend' => { label=>'Suspension command',
default=>'',
},
@@ -47,10 +44,6 @@ tie my %options, 'Tie::IxHash',
'unsuspend_stdin' => { label=>'Unsuspension command STDIN',
default=>'',
},
- 'crypt' => { label => 'Default password encryption',
- type=>'select', options=>[qw(crypt md5)],
- default => 'crypt',
- },
;
%info = (
@@ -92,8 +85,8 @@ The following variables are available for interpolation (prefixed with
<LI><code>$username</code>
<LI><code>$domain</code>
<LI><code>$_password</code>
- <LI><code>$quoted_password</code> - unencrypted password, already quoted for the shell (do not add additional quotes)
- <LI><code>$crypt_password</code> - encrypted password, already quoted for the shell (do not add additional quotes)
+ <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)
diff --git a/FS/FS/part_export/sqlradius.pm b/FS/FS/part_export/sqlradius.pm
index 10bccb034..e1d862c39 100644
--- a/FS/FS/part_export/sqlradius.pm
+++ b/FS/FS/part_export/sqlradius.pm
@@ -2,10 +2,8 @@ package FS::part_export::sqlradius;
use vars qw(@ISA $DEBUG %info %options $notes1 $notes2);
use Tie::IxHash;
-use FS::Record qw( dbh qsearch );
+use FS::Record qw( dbh );
use FS::part_export;
-use FS::svc_acct;
-use FS::export_svc;
@ISA = qw(FS::part_export);
@@ -34,10 +32,10 @@ tie %options, 'Tie::IxHash',
;
$notes1 = <<'END';
-Real-time export of <b>radcheck</b>, <b>radreply</b> and <b>usergroup</b>
-tables to any SQL database for
-<a href="http://www.freeradius.org/">FreeRADIUS</a>
-or <a href="http://radius.innercite.com/">ICRADIUS</a>.
+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>.
END
$notes2 = <<'END';
@@ -66,7 +64,7 @@ END
%info = (
'svc' => 'svc_acct',
- 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS)',
+ 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS, Radiator)',
'options' => \%options,
'nodomain' => 'Y',
'notes' => $notes1.
@@ -368,6 +366,7 @@ Called-Station-ID.
#SQL_SELECT defaults to * if unspecified. It can be useful to set it to
#SUM(acctsessiontime) or SUM(AcctInputOctets), etc.
+Returns an array of hash references
Returns an arrayref of hashrefs with the following fields:
=over 4
@@ -468,85 +467,5 @@ sub usage_sessions {
}
-=item update_svc_acct
-
-=cut
-
-sub update_svc_acct {
- my $self = shift;
-
- my $dbh = sqlradius_connect( map $self->option($_),
- qw( datasrc username password ) );
-
- my @fields = qw( radacctid username realm acctsessiontime );
-
- my @param = ();
- my $where = '';
-
- my $sth = $dbh->prepare("
- SELECT RadAcctId, UserName, Realm, AcctSessionTime
- FROM radacct
- WHERE FreesideStatus IS NULL
- AND AcctStopTime != 0
- ") or die $dbh->errstr;
- $sth->execute() or die $sth->errstr;
-
- while ( my $row = $sth->fetchrow_arrayref ) {
- my($RadAcctId, $UserName, $Realm, $AcctSessionTime) = @$row;
- warn "processing record: ".
- "$RadAcctId ($UserName\@$Realm for ${AcctSessionTime}s"
- if $DEBUG;
-
- my %search = ( 'username' => $UserName );
- my $extra_sql = '';
- if ( ref($self) =~ /withdomain/ ) { #well...
- $extra_sql = " AND '$Realm' = ( SELECT domain FROM svc_domain
- WHERE svc_domain.svcnum = svc_acct.domsvc ) ";
- my $svc_domain = qsearch
- }
-
- my @svc_acct =
- grep { qsearch( 'export_svc', { 'exportnum' => $self->exportnum,
- 'svcpart' => $_->cust_svc->svcpart, } )
- }
- qsearch( 'svc_acct',
- { 'username' => $UserName },
- '',
- $extra_sql
- );
-
- my $errinfo = "for RADIUS detail RadAcctID $RadAcctId ".
- "(UserName $UserName, Realm $Realm)";
- my $status = 'skipped';
- if ( !@svc_acct ) {
- warn "WARNING: no svc_acct record found $errinfo - skipping\n";
- } elsif ( scalar(@svc_acct) > 1 ) {
- warn "WARNING: multiple svc_acct records found $errinfo - skipping\n";
- } else {
- my $svc_acct = $svc_acct[0];
- warn "found svc_acct ". $svc_acct->svcnum. " $errinfo\n" if $DEBUG;
- if ( $svc_acct->seconds !~ /^$/ ) {
- warn " svc_acct.seconds found (". $svc_acct->seconds.
- ") - decrementing\n"
- if $DEBUG;
- my $error = $svc_acct->decrement_seconds($AcctSessionTime);
- die $error if $error;
- $status = 'done';
- } else {
- warn " no existing seconds value for svc_acct - skiping\n" if $DEBUG;
- }
- }
-
- warn "setting FreesideStatus to $status $errinfo\n" if $DEBUG;
- my $psth = $dbh->prepare("UPDATE radacct
- SET FreesideStatus = ?
- WHERE RadAcctId = ?"
- ) or die $dbh->errstr;
- $psth->execute($status, $RadAcctId) or die $psth->errstr;
-
- }
-
-}
-
1;
diff --git a/FS/FS/part_export/sqlradius_withdomain.pm b/FS/FS/part_export/sqlradius_withdomain.pm
index e5a7151a2..6130e5eb6 100644
--- a/FS/FS/part_export/sqlradius_withdomain.pm
+++ b/FS/FS/part_export/sqlradius_withdomain.pm
@@ -8,7 +8,7 @@ tie my %options, 'Tie::IxHash', %FS::part_export::sqlradius::options;
%info = (
'svc' => 'svc_acct',
- 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS) with realms',
+ 'desc' => 'Real-time export to SQL-backed RADIUS (FreeRADIUS, ICRADIUS, Radiator) with realms',
'options' => \%options,
'nodomain' => '',
'notes' => $FS::part_export::sqlradius::notes1.
diff --git a/FS/FS/part_export/www_shellcommands.pm b/FS/FS/part_export/www_shellcommands.pm
index 9d3564e12..0e50d607c 100644
--- a/FS/FS/part_export/www_shellcommands.pm
+++ b/FS/FS/part_export/www_shellcommands.pm
@@ -80,7 +80,6 @@ sub _export_delete {
sub _export_command {
my ( $self, $action, $svc_www) = (shift, shift, shift);
my $command = $self->option($action);
- return '' if $command =~ /^\s*$/;
#set variable for the command
no strict 'vars';
diff --git a/FS/FS/part_export_option.pm b/FS/FS/part_export_option.pm
index e75940429..33b5e5a67 100644
--- a/FS/FS/part_export_option.pm
+++ b/FS/FS/part_export_option.pm
@@ -104,7 +104,7 @@ sub check {
my $error =
$self->ut_numbern('optionnum')
- || $self->ut_foreign_key('exportnum', 'part_export', 'exportnum')
+ || $self->ut_number('exportnum')
|| $self->ut_alpha('optionname')
|| $self->ut_anything('optionvalue')
;
diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm
index 73f3bae04..cef4a612a 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 %freq %plans $DEBUG );
-use Carp qw(carp cluck confess);
+use Carp qw(carp cluck);
use Tie::IxHash;
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh dbdef );
@@ -13,9 +13,7 @@ use FS::agent_type;
use FS::type_pkgs;
use FS::part_pkg_option;
-@ISA = qw( FS::Record ); # FS::option_Common ); # this can use option_Common
- # when all the plandata bs is
- # gone
+@ISA = qw( FS::Record );
$DEBUG = 0;
@@ -118,8 +116,8 @@ sub clone {
Adds this package definition to the database. If there is an error,
returns the error, otherwise returns false.
-Currently available options are: I<pkg_svc>, I<primary_svc>, I<cust_pkg>,
-I<custnum_ref> and I<options>.
+Currently available options are: I<pkg_svc>, I<primary_svc>, I<cust_pkg> and
+I<custnum_ref>.
If I<pkg_svc> is set to a hashref with svcparts as keys and quantities as
values, appropriate FS::pkg_svc records will be inserted.
@@ -133,9 +131,6 @@ record itself), the object will be updated to point to this package definition.
In conjunction with I<cust_pkg>, if I<custnum_ref> is set to a scalar reference,
the scalar will be updated with the custnum value from the cust_pkg record.
-If I<options> is set to a hashref of options, appropriate FS::part_pkg_option
-records will be inserted.
-
=cut
sub insert {
@@ -168,8 +163,7 @@ sub insert {
}
if ( $plandata ) {
-
- warn " inserting part_pkg_option records for plandata" if $DEBUG;
+ warn " inserting part_pkg_option records for plandata" if $DEBUG;
foreach my $part_pkg_option (
map { /^(\w+)=(.*)$/ or do { $dbh->rollback if $oldAutoCommit;
return "illegal plandata: $plandata";
@@ -188,27 +182,6 @@ sub insert {
return $error;
}
}
-
- } elsif ( $options{'options'} ) {
-
- warn " inserting part_pkg_option records for options hashref" if $DEBUG;
- foreach my $optionname ( keys %{$options{'options'}} ) {
-
- my $part_pkg_option =
- new FS::part_pkg_option {
- 'pkgpart' => $self->pkgpart,
- 'optionname' => $optionname,
- 'optionvalue' => $options{'options'}->{$optionname},
- };
-
- my $error = $part_pkg_option->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- }
-
}
my $conf = new FS::Conf;
@@ -232,10 +205,7 @@ sub insert {
my $pkg_svc = $options{'pkg_svc'} || {};
foreach my $part_svc ( qsearch('part_svc', {} ) ) {
my $quantity = $pkg_svc->{$part_svc->svcpart} || 0;
- my $primary_svc =
- ( $options{'primary_svc'} && $options{'primary_svc'}==$part_svc->svcpart )
- ? 'Y'
- : '';
+ my $primary_svc = $options{'primary_svc'} == $part_svc->svcpart ? 'Y' : '';
my $pkg_svc = new FS::pkg_svc( {
'pkgpart' => $self->pkgpart,
@@ -377,7 +347,6 @@ sub replace {
next unless $old_quantity != $quantity || $old_primary_svc ne $primary_svc;
my $new_pkg_svc = new FS::pkg_svc( {
- 'pkgsvcnum' => ( $old_pkg_svc ? $old_pkg_svc->pkgsvcnum : '' ),
'pkgpart' => $new->pkgpart,
'svcpart' => $part_svc->svcpart,
'quantity' => $quantity,
@@ -420,7 +389,7 @@ sub check {
my $error = $self->ut_number('freq');
return $error if $error;
} else {
- $self->freq =~ /^(\d+[hdw]?)$/
+ $self->freq =~ /^(\d+[dw]?)$/
or return "Illegal or empty freq: ". $self->freq;
$self->freq($1);
}
@@ -441,10 +410,6 @@ sub check {
return 'Unknown plan '. $self->plan
unless exists($plans{$self->plan});
- my $conf = new FS::Conf;
- return 'Taxclass is required'
- if ! $self->taxclass && $conf->exists('require_taxclasses');
-
'';
}
@@ -539,7 +504,6 @@ Returns an english representation of the I<freq> field, such as "monthly",
tie %freq, 'Tie::IxHash',
'0' => '(no recurring fee)',
- '1h' => 'hourly',
'1d' => 'daily',
'1w' => 'weekly',
'2w' => 'biweekly (every 2 weeks)',
@@ -549,10 +513,6 @@ tie %freq, 'Tie::IxHash',
'6' => 'semiannually (every 6 months)',
'12' => 'annually',
'24' => 'biannually (every 2 years)',
- '36' => 'triannually (every 3 years)',
- '48' => '(every 4 years)',
- '60' => '(every 5 years)',
- '120' => '(every 10 years)',
;
sub freq_pretty {
@@ -562,8 +522,8 @@ sub freq_pretty {
$freq{$freq};
} else {
my $interval = 'month';
- if ( $freq =~ /^(\d+)([hdw])$/ ) {
- my %interval = ( 'h' => 'hour', 'd'=>'day', 'w'=>'week' );
+ if ( $freq =~ /^(\d+)([dw])$/ ) {
+ my %interval = ( 'd'=>'day', 'w'=>'week' );
$interval = $interval{$2};
}
if ( $1 == 1 ) {
@@ -624,7 +584,7 @@ Returns the option value for the given name, or the empty string.
=cut
sub option {
- my( $self, $opt, $ornull ) = @_;
+ my( $self, $opt ) = @_;
my $part_pkg_option =
qsearchs('part_pkg_option', {
pkgpart => $self->pkgpart,
@@ -634,8 +594,7 @@ sub option {
my %plandata = map { /^(\w+)=(.*)$/; ( $1 => $2 ); }
split("\n", $self->get('plandata') );
return $plandata{$opt} if exists $plandata{$opt};
- cluck "Package definition option $opt not found in options or plandata!\n"
- unless $ornull;
+ cluck "Package definition option $opt not found in options or plandata!\n";
'';
}
@@ -650,16 +609,9 @@ on how to create new price plans, but until then, see L</NEW PLAN CLASSES>.
sub _rebless {
my $self = shift;
my $plan = $self->plan;
- unless ( $plan ) {
- confess "no price plan found for pkgpart ". $self->pkgpart. "\n"
- if $DEBUG;
- return $self;
- }
- return $self if ref($self) =~ /::$plan$/; #already blessed into plan subclass
my $class = ref($self). "::$plan";
- warn "reblessing $self into $class" if $DEBUG;
eval "use $class;";
- die $@ if $@;
+ #die $@ if $@;
bless($self, $class) unless $@;
$self;
}
@@ -694,11 +646,6 @@ sub _calc_eval {
$value;
}
-#fallback that return 0 for old legacy packages with no plan
-
-sub calc_remain { 0; }
-sub calc_cancel { 0; }
-
=back
=head1 SUBROUTINES
@@ -711,7 +658,6 @@ sub calc_cancel { 0; }
my %info;
foreach my $INC ( @INC ) {
- warn "globbing $INC/FS/part_pkg/*.pm\n" if $DEBUG;
foreach my $file ( glob("$INC/FS/part_pkg/*.pm") ) {
warn "attempting to load plan info from $file\n" if $DEBUG;
$file =~ /\/(\w+)\.pm$/ or do {
@@ -762,8 +708,6 @@ The delete method is unimplemented.
setup and recur semantics are not yet defined (and are implemented in
FS::cust_bill. hmm.).
-plandata should go
-
=head1 SEE ALSO
L<FS::Record>, L<FS::cust_pkg>, L<FS::type_pkgs>, L<FS::pkg_svc>, L<Safe>.
diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm
index 59b625746..b62aebd7d 100644
--- a/FS/FS/part_pkg/flat.pm
+++ b/FS/FS/part_pkg/flat.pm
@@ -10,18 +10,14 @@ use FS::part_pkg;
%info = (
'name' => 'Flat rate (anniversary billing)',
'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
},
- 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit' ],
+ 'fieldorder' => [ 'setup_fee', 'recur_fee' ],
#'setup' => 'what.setup_fee.value',
#'recur' => 'what.recur_fee.value',
'weight' => 10,
@@ -33,48 +29,12 @@ sub calc_setup {
}
sub calc_recur {
- my $self = shift;
- $self->base_recur(@_);
-}
-
-sub base_recur {
- my($self, $cust_pkg) = @_;
+ my($self, $cust_pkg ) = @_;
$self->option('recur_fee');
}
-sub calc_remain {
- my ($self, $cust_pkg) = @_;
- my $time = time; #should be able to pass this in for credit calculation
- my $next_bill = $cust_pkg->getfield('bill') || 0;
- my $last_bill = $cust_pkg->last_bill || 0;
- return 0 if ! $self->base_recur
- || ! $self->option('unused_credit', 1)
- || ! $last_bill
- || ! $next_bill
- || $next_bill < $time;
-
- my %sec = (
- 'h' => 3600, # 60 * 60
- 'd' => 86400, # 60 * 60 * 24
- 'w' => 604800, # 60 * 60 * 24 * 7
- 'm' => 2629744, # 60 * 60 * 24 * 365.2422 / 12
- );
-
- $self->freq =~ /^(\d+)([hdwm]?)$/
- or die 'unparsable frequency: '. $self->freq;
- my $freq_sec = $1 * $sec{$2||'m'};
- return 0 unless $freq_sec;
-
- sprintf("%.2f", $self->base_recur * ( $next_bill - $time ) / $freq_sec );
-
-}
-
sub is_free_options {
qw( setup_fee recur_fee );
}
-sub is_prepaid {
- 0; #no, we're postpaid
-}
-
1;
diff --git a/FS/FS/part_pkg/flat_comission.pm b/FS/FS/part_pkg/flat_comission.pm
index 442415e08..9b288c3a3 100644
--- a/FS/FS/part_pkg/flat_comission.pm
+++ b/FS/FS/part_pkg/flat_comission.pm
@@ -3,34 +3,30 @@ package FS::part_pkg::flat_comission;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Flat rate with recurring commission per (any) active package',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'comission_amount' => { 'name' => 'Commission amount per month (per active package)',
- 'default' => 0,
- },
- 'comission_depth' => { 'name' => 'Number of layers',
- 'default' => 1,
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
- 'weight' => 62,
+ 'name' => 'Flat rate with recurring commission per (any) active package',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+ 'comission_amount' => { 'name' => 'Commission amount per month (per active package)',
+ 'default' => 0,
+ },
+ 'comission_depth' => { 'name' => 'Number of layers',
+ 'default' => 1,
+ },
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
+ 'weight' => 62,
);
sub calc_recur {
diff --git a/FS/FS/part_pkg/flat_comission_cust.pm b/FS/FS/part_pkg/flat_comission_cust.pm
index 4abe66ad2..8aa993ca6 100644
--- a/FS/FS/part_pkg/flat_comission_cust.pm
+++ b/FS/FS/part_pkg/flat_comission_cust.pm
@@ -3,34 +3,30 @@ package FS::part_pkg::flat_comission_cust;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Flat rate with recurring commission per active customer',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'comission_amount' => { 'name' => 'Commission amount per month (per active customer)',
- 'default' => 0,
- },
- 'comission_depth' => { 'name' => 'Number of layers',
- 'default' => 1,
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_main_ncancelled(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
- 'weight' => '60',
+ 'name' => 'Flat rate with recurring commission per active customer',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+ 'comission_amount' => { 'name' => 'Commission amount per month (per active customer)',
+ 'default' => 0,
+ },
+ 'comission_depth' => { 'name' => 'Number of layers',
+ 'default' => 1,
+ },
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar($cust_pkg->cust_main->referral_cust_main_ncancelled(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
+ 'weight' => '60',
);
sub calc_recur {
@@ -38,16 +34,13 @@ sub calc_recur {
my $amount = $self->option('comission_amount');
my $num_active = scalar(
- $cust_pkg->cust_main->referral_cust_main_ncancelled(
+ $cust_pkg->cust_main->referral_cust_pkgcust_main_ncancelled(
$self->option('comission_depth')
)
);
- if ( $amount && $num_active ) {
- my $error =
- $cust_pkg->cust_main->credit( $amount*$num_active, "commission" );
- die $error if $error;
- }
+ my $error = $cust_pkg->cust_main->credit( $amount*$num_active, "commission" );
+ die $error if $error;
$self->option('recur_fee');
}
diff --git a/FS/FS/part_pkg/flat_comission_pkg.pm b/FS/FS/part_pkg/flat_comission_pkg.pm
index 0f4d02a58..befa77e23 100644
--- a/FS/FS/part_pkg/flat_comission_pkg.pm
+++ b/FS/FS/part_pkg/flat_comission_pkg.pm
@@ -3,42 +3,38 @@ package FS::part_pkg::flat_comission_pkg;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Flat rate with recurring commission per (selected) active package',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'comission_amount' => { 'name' => 'Commission amount per month (per uncancelled package)',
- 'default' => 0,
- },
- 'comission_depth' => { 'name' => 'Number of layers',
- 'default' => 1,
- },
- 'comission_pkgpart' => { 'name' => 'Applicable packages<BR><FONT SIZE="-1">(hold <b>ctrl</b> to select multiple packages)</FONT>',
- 'type' => 'select_multiple',
- 'select_table' => 'part_pkg',
- 'select_hash' => { 'disabled' => '' } ,
- 'select_key' => 'pkgpart',
- 'select_label' => 'pkg',
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit', 'comission_depth', 'comission_amount', 'comission_pkgpart' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '""; var pkgparts = ""; for ( var c=0; c < document.flat_comission_pkg.comission_pkgpart.options.length; c++ ) { if (document.flat_comission_pkg.comission_pkgpart.options[c].selected) { pkgparts = pkgparts + document.flat_comission_pkg.comission_pkgpart.options[c].value + \', \'; } } what.recur.value = \'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar( grep { my $pkgpart = $_->pkgpart; grep { $_ == $pkgpart } ( \' + pkgparts + \' ) } $cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
- #'disabled' => 1,
- 'weight' => '64',
+ 'name' => 'Flat rate with recurring commission per (selected) active package',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+ 'comission_amount' => { 'name' => 'Commission amount per month (per uncancelled package)',
+ 'default' => 0,
+ },
+ 'comission_depth' => { 'name' => 'Number of layers',
+ 'default' => 1,
+ },
+ 'comission_pkgpart' => { 'name' => 'Applicable packages<BR><FONT SIZE="-1">(hold <b>ctrl</b> to select multiple packages)</FONT>',
+ 'type' => 'select_multiple',
+ 'select_table' => 'part_pkg',
+ 'select_hash' => { 'disabled' => '' } ,
+ 'select_key' => 'pkgpart',
+ 'select_label' => 'pkg',
+ },
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_fee', 'comission_depth', 'comission_amount', 'comission_pkgpart' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '""; var pkgparts = ""; for ( var c=0; c < document.flat_comission_pkg.comission_pkgpart.options.length; c++ ) { if (document.flat_comission_pkg.comission_pkgpart.options[c].selected) { pkgparts = pkgparts + document.flat_comission_pkg.comission_pkgpart.options[c].value + \', \'; } } what.recur.value = \'my $error = $cust_pkg->cust_main->credit( \' + what.comission_amount.value + \' * scalar( grep { my $pkgpart = $_->pkgpart; grep { $_ == $pkgpart } ( \' + pkgparts + \' ) } $cust_pkg->cust_main->referral_cust_pkg(\' + what.comission_depth.value+ \')), "commission" ); die $error if $error; \' + what.recur_fee.value + \';\'',
+ #'disabled' => 1,
+ 'weight' => '64',
);
# XXX this needs to be fixed!!!
diff --git a/FS/FS/part_pkg/flat_delayed.pm b/FS/FS/part_pkg/flat_delayed.pm
index ec11699d9..f39783fd6 100644
--- a/FS/FS/part_pkg/flat_delayed.pm
+++ b/FS/FS/part_pkg/flat_delayed.pm
@@ -3,32 +3,28 @@ package FS::part_pkg::flat_delayed;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Free (or setup fee) for X days, then flat rate'.
- ' (anniversary billing)',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'free_days' => { 'name' => 'Initial free days',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- },
- 'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee', 'unused_credit' ],
- #'setup' => '\'my $d = $cust_pkg->bill || $time; $d += 86400 * \' + what.free_days.value + \'; $cust_pkg->bill($d); $cust_pkg_mod_flag=1; \' + what.setup_fee.value',
- #'recur' => 'what.recur_fee.value',
- 'weight' => 50,
+ 'name' => 'Free (or setup fee) for X days, then flat rate'.
+ ' (anniversary billing)',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'free_days' => { 'name' => 'Initial free days',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+ },
+ 'fieldorder' => [ 'free_days', 'setup_fee', 'recur_fee' ],
+ #'setup' => '\'my $d = $cust_pkg->bill || $time; $d += 86400 * \' + what.free_days.value + \'; $cust_pkg->bill($d); $cust_pkg_mod_flag=1; \' + what.setup_fee.value',
+ #'recur' => 'what.recur_fee.value',
+ 'weight' => 50,
);
sub calc_setup {
diff --git a/FS/FS/part_pkg/prepaid.pm b/FS/FS/part_pkg/prepaid.pm
deleted file mode 100644
index 5e7d2baae..000000000
--- a/FS/FS/part_pkg/prepaid.pm
+++ /dev/null
@@ -1,28 +0,0 @@
-package FS::part_pkg::prepaid;
-
-use strict;
-use vars qw(@ISA %info);
-use FS::part_pkg::flat;
-
-@ISA = qw(FS::part_pkg::flat);
-
-%info = (
- 'name' => 'Prepaid, flat rate',
- 'fields' => {
- 'setup_fee' => { 'name' => 'One-time setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Initial and recharge fee for this package',
- 'default' => 0,
- }
- },
- 'fieldorder' => [ 'setup_fee', 'recur_fee', ],
- 'weight' => 25,
-);
-
-sub is_prepaid {
- 1;
-}
-
-1;
-
diff --git a/FS/FS/part_pkg/prorate.pm b/FS/FS/part_pkg/prorate.pm
index 86c64d53a..d27adbda7 100644
--- a/FS/FS/part_pkg/prorate.pm
+++ b/FS/FS/part_pkg/prorate.pm
@@ -4,29 +4,25 @@ use strict;
use vars qw(@ISA %info);
use Time::Local qw(timelocal);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'First partial month pro-rated, then flat-rate (1st of month billing)',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_fee', 'unused_credit' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; my $mstart = timelocal(0,0,0,1,$mon,$year); my $mend = timelocal(0,0,0,1, $mon == 11 ? 0 : $mon+1, $year+($mon==11)); $sdate = $mstart; ( $part_pkg->freq - 1 ) * \' + what.recur_fee.value + \' / $part_pkg->freq + \' + what.recur_fee.value + \' / $part_pkg->freq * ($mend-$mnow) / ($mend-$mstart) ; \'',
- 'freq' => 'm',
- 'weight' => 20,
+ 'name' => 'First partial month pro-rated, then flat-rate (1st of month billing)',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_fee' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; my $mstart = timelocal(0,0,0,1,$mon,$year); my $mend = timelocal(0,0,0,1, $mon == 11 ? 0 : $mon+1, $year+($mon==11)); $sdate = $mstart; ( $part_pkg->freq - 1 ) * \' + what.recur_fee.value + \' / $part_pkg->freq + \' + what.recur_fee.value + \' / $part_pkg->freq * ($mend-$mnow) / ($mend-$mstart) ; \'',
+ 'freq' => 'm',
+ 'weight' => 20,
);
sub calc_recur {
diff --git a/FS/FS/part_pkg/sesmon_hour.pm b/FS/FS/part_pkg/sesmon_hour.pm
index 9843edbec..0367b2b4c 100644
--- a/FS/FS/part_pkg/sesmon_hour.pm
+++ b/FS/FS/part_pkg/sesmon_hour.pm
@@ -3,34 +3,30 @@ package FS::part_pkg::sesmon_hour;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Base charge plus charge per-hour from the session monitor',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_flat' => { 'name' => 'Base recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'recur_included_hours' => { 'name' => 'Hours included',
- 'default' => 0,
- },
- 'recur_hourly_charge' => { 'name' => 'Additional charge per hour',
- 'default' => 0,
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_flat', 'unused_credit', 'recur_included_hours', 'recur_hourly_charge' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $hours = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'',
- 'weight' => 80,
+ 'name' => 'Base charge plus charge per-hour from the session monitor',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_flat' => { 'name' => 'Base monthly charge for this package',
+ 'default' => 0,
+ },
+ 'recur_included_hours' => { 'name' => 'Hours included',
+ 'default' => 0,
+ },
+ 'recur_hourly_charge' => { 'name' => 'Additional charge per hour',
+ 'default' => 0,
+ },
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_flat', 'recur_included_hours', 'recur_hourly_charge' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $hours = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'',
+ 'weight' => 80,
);
sub calc_recur {
@@ -48,9 +44,4 @@ sub is_free_options {
qw( setup_fee recur_fee recur_hourly_charge );
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_flat');
-}
-
1;
diff --git a/FS/FS/part_pkg/sesmon_minute.pm b/FS/FS/part_pkg/sesmon_minute.pm
index 39516f8b3..7cafbe056 100644
--- a/FS/FS/part_pkg/sesmon_minute.pm
+++ b/FS/FS/part_pkg/sesmon_minute.pm
@@ -3,38 +3,34 @@ package FS::part_pkg::sesmon_minute;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Base charge plus charge per-minute from the session monitor',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_flat' => { 'name' => 'Base recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'recur_included_min' => { 'name' => 'Minutes included',
- 'default' => 0,
+ 'name' => 'Base charge plus charge per-minute from the session monitor',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_flat' => { 'name' => 'Base monthly charge for this package',
+ 'default' => 0,
+ },
+ 'recur_included_min' => { 'name' => 'Minutes included',
+ 'default' => 0,
+ },
+ 'recur_minly_charge' => { 'name' => 'Additional charge per minute',
+ 'default' => 0,
},
- 'recur_minly_charge' => { 'name' => 'Additional charge per minute',
- 'default' => 0,
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_flat', 'unused_credit', 'recur_included_min', 'recur_minly_charge' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $min = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 60 - \' + what.recur_included_min.value + \'; $min = 0 if $min < 0; \' + what.recur_flat.value + \' + \' + what.recur_minly_charge.value + \' * $min;\'',
- 'weight' => 80,
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_flat', 'recur_included_min', 'recur_minly_charge' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $min = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 60 - \' + what.recur_included_min.value + \'; $min = 0 if $min < 0; \' + what.recur_flat.value + \' + \' + what.recur_minly_charge.value + \' * $min;\'',
+ 'weight' => 80,
);
-sub calc_recur {
+sub cakc_recur {
my( $self, $cust_pkg ) = @);
my $min = $cust_pkg->seconds_since($cust_pkg->bill || 0) / 60;
$min -= $self->option('recur_included_min');
@@ -47,9 +43,4 @@ sub is_free_options {
qw( setup_fee recur_fee recur_minly_charge );
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_flat');
-}
-
1;
diff --git a/FS/FS/part_pkg/sql_external.pm b/FS/FS/part_pkg/sql_external.pm
index ca58c4e66..8da4d3135 100644
--- a/FS/FS/part_pkg/sql_external.pm
+++ b/FS/FS/part_pkg/sql_external.pm
@@ -4,40 +4,36 @@ use strict;
use vars qw(@ISA %info);
use DBI;
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Base charge plus additional fees for external services from a configurable SQL query',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
+ 'name' => 'Base charge plus additional fees for external services from a configurable SQL query',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_flat' => { 'name' => 'Base monthly charge for this package',
+ 'default' => 0,
+ },
+ 'datasrc' => { 'name' => 'DBI data source',
+ 'default' => '',
},
- 'recur_flat' => { 'name' => 'Base recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
+ 'db_username' => { 'name' => 'Database username',
+ 'default' => '',
+ },
+ 'db_password' => { 'name' => 'Database password',
+ 'default' => '',
},
- 'datasrc' => { 'name' => 'DBI data source',
+ 'query' => { 'name' => 'SQL query',
'default' => '',
},
- 'db_username' => { 'name' => 'Database username',
- 'default' => '',
- },
- 'db_password' => { 'name' => 'Database password',
- 'default' => '',
- },
- 'query' => { 'name' => 'SQL query',
- 'default' => '',
- },
- },
- 'fieldorder' => [qw( setup_fee recur_flat unused_credit datasrc db_username db_password query )],
- #'setup' => 'what.setup_fee.value',
- #'recur' => q!'my $dbh = DBI->connect("' + what.datasrc.value + '", "' + what.db_username.value + '", "' + what.db_password.value + '" ) or die $DBI::errstr; my $sth = $dbh->prepare("' + what.query.value + '") or die $dbh->errstr; my $price = ' + what.recur_flat.value + '; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq "svc_external" } $cust_pkg->cust_svc ){ my $id = $cust_svc->svc_x->id; $sth->execute($id) or die $sth->errstr; $price += $sth->fetchrow_arrayref->[0]; } $price;'!,
- 'weight' => '72',
+ },
+ 'fieldorder' => [qw( setup_fee recur_flat datasrc db_username db_password query )],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => q!'my $dbh = DBI->connect("' + what.datasrc.value + '", "' + what.db_username.value + '", "' + what.db_password.value + '" ) or die $DBI::errstr; my $sth = $dbh->prepare("' + what.query.value + '") or die $dbh->errstr; my $price = ' + what.recur_flat.value + '; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq "svc_external" } $cust_pkg->cust_svc ){ my $id = $cust_svc->svc_x->id; $sth->execute($id) or die $sth->errstr; $price += $sth->fetchrow_arrayref->[0]; } $price;'!,
+ 'weight' => '72',
);
sub calc_recur {
@@ -68,9 +64,4 @@ sub is_free {
0;
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_flat');
-}
-
1;
diff --git a/FS/FS/part_pkg/sql_generic.pm b/FS/FS/part_pkg/sql_generic.pm
index 0e6ab7c0d..b7c7008c1 100644
--- a/FS/FS/part_pkg/sql_generic.pm
+++ b/FS/FS/part_pkg/sql_generic.pm
@@ -4,48 +4,44 @@ use strict;
use vars qw(@ISA %info);
use DBI;
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Base charge plus a per-domain metered rate from a configurable SQL query',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
+ 'name' => 'Base charge plus a per-domain metered rate from a configurable SQL query',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_flat' => { 'name' => 'Base monthly charge for this package',
+ 'default' => 0,
+ },
+ 'recur_included' => { 'name' => 'Units included',
+ 'default' => 0,
+ },
+ 'recur_unit_charge' => { 'name' => 'Additional charge per unit',
+ 'default' => 0,
+ },
+ 'datasrc' => { 'name' => 'DBI data source',
+ 'default' => '',
},
- 'recur_flat' => { 'name' => 'Base recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
+ 'db_username' => { 'name' => 'Database username',
+ 'default' => '',
+ },
+ 'db_password' => { 'name' => 'Database username',
+ 'default' => '',
},
- 'recur_included' => { 'name' => 'Units included',
- 'default' => 0,
- },
- 'recur_unit_charge' => { 'name' => 'Additional charge per unit',
- 'default' => 0,
- },
- 'datasrc' => { 'name' => 'DBI data source',
+ 'query' => { 'name' => 'SQL query',
'default' => '',
},
- 'db_username' => { 'name' => 'Database username',
- 'default' => '',
- },
- 'db_password' => { 'name' => 'Database username',
- 'default' => '',
- },
- 'query' => { 'name' => 'SQL query',
- 'default' => '',
- },
- },
- 'fieldorder' => [qw( setup_fee recur_flat unused_credit recur_included recur_unit_charge datasrc db_username db_password query )],
- # 'setup' => 'what.setup_fee.value',
- # 'recur' => '\'my $dbh = DBI->connect(\"\' + what.datasrc.value + \'\", \"\' + what.db_username.value + \'\") or die $DBI::errstr; \'',
- #'recur' => '\'my $dbh = DBI->connect(\"\' + what.datasrc.value + \'\", \"\' + what.db_username.value + \'\", \"\' + what.db_password.value + \'\" ) or die $DBI::errstr; my $sth = $dbh->prepare(\"\' + what.query.value + \'\") or die $dbh->errstr; my $units = 0; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq \"svc_domain\" } $cust_pkg->cust_svc ) { my $domain = $cust_svc->svc_x->domain; $sth->execute($domain) or die $sth->errstr; $units += $sth->fetchrow_arrayref->[0]; } $units -= \' + what.recur_included.value + \'; $units = 0 if $units < 0; \' + what.recur_flat.value + \' + $units * \' + what.recur_unit_charge.value + \';\'',
- #'recur' => '\'my $dbh = DBI->connect("\' + what.datasrc.value + \'", "\' + what.db_username.value + \'", "\' what.db_password.value + \'" ) or die $DBI::errstr; my $sth = $dbh->prepare("\' + what.query.value + \'") or die $dbh->errstr; my $units = 0; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq "svc_domain" } $cust_pkg->cust_svc ) { my $domain = $cust_svc->svc_x->domain; $sth->execute($domain) or die $sth->errstr; $units += $sth->fetchrow_arrayref->[0]; } $units -= \' + what.recur_included.value + \'; $units = 0 if $units < 0; \' + what.recur_flat.value + \' + $units * \' + what.recur_unit_charge + \';\'',
- 'weight' => '70',
+ },
+ 'fieldorder' => [qw( setup_fee recur_flat recur_included recur_unit_charge datasrc db_username db_password query )],
+ # 'setup' => 'what.setup_fee.value',
+ # 'recur' => '\'my $dbh = DBI->connect(\"\' + what.datasrc.value + \'\", \"\' + what.db_username.value + \'\") or die $DBI::errstr; \'',
+ #'recur' => '\'my $dbh = DBI->connect(\"\' + what.datasrc.value + \'\", \"\' + what.db_username.value + \'\", \"\' + what.db_password.value + \'\" ) or die $DBI::errstr; my $sth = $dbh->prepare(\"\' + what.query.value + \'\") or die $dbh->errstr; my $units = 0; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq \"svc_domain\" } $cust_pkg->cust_svc ) { my $domain = $cust_svc->svc_x->domain; $sth->execute($domain) or die $sth->errstr; $units += $sth->fetchrow_arrayref->[0]; } $units -= \' + what.recur_included.value + \'; $units = 0 if $units < 0; \' + what.recur_flat.value + \' + $units * \' + what.recur_unit_charge.value + \';\'',
+ #'recur' => '\'my $dbh = DBI->connect("\' + what.datasrc.value + \'", "\' + what.db_username.value + \'", "\' what.db_password.value + \'" ) or die $DBI::errstr; my $sth = $dbh->prepare("\' + what.query.value + \'") or die $dbh->errstr; my $units = 0; foreach my $cust_svc ( grep { $_->part_svc->svcdb eq "svc_domain" } $cust_pkg->cust_svc ) { my $domain = $cust_svc->svc_x->domain; $sth->execute($domain) or die $sth->errstr; $units += $sth->fetchrow_arrayref->[0]; } $units -= \' + what.recur_included.value + \'; $units = 0 if $units < 0; \' + what.recur_flat.value + \' + $units * \' + what.recur_unit_charge + \';\'',
+ 'weight' => '70',
);
sub calc_recur {
@@ -79,9 +75,4 @@ sub is_free_options {
qw( setup_fee recur_flat recur_unit_charge );
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_flat');
-}
-
1;
diff --git a/FS/FS/part_pkg/sqlradacct_hour.pm b/FS/FS/part_pkg/sqlradacct_hour.pm
index e54a8a553..a2550e241 100644
--- a/FS/FS/part_pkg/sqlradacct_hour.pm
+++ b/FS/FS/part_pkg/sqlradacct_hour.pm
@@ -3,83 +3,52 @@ package FS::part_pkg::sqlradacct_hour;
use strict;
use vars qw(@ISA %info);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'Base charge plus per-hour (and for data) from an SQL RADIUS radacct table',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_flat' => { 'name' => 'Base recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
-
- 'recur_included_hours' => { 'name' => 'Hours included',
+ 'name' => 'Base charge plus per-hour (and for data) from an SQL RADIUS radacct table',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_flat' => { 'name' => 'Base monthly charge for this package',
+ 'default' => 0,
+ },
+ 'recur_included_hours' => { 'name' => 'Hours included',
+ 'default' => 0,
+ },
+ 'recur_hourly_charge' => { 'name' => 'Additional charge per hour',
+ 'default' => 0,
+ },
+ 'recur_included_input' => { 'name' => 'Upload megabytes included',
+ 'default' => 0,
+ },
+ 'recur_input_charge' => { 'name' =>
+ 'Additional charge per megabyte upload',
'default' => 0,
},
- 'recur_hourly_charge' => { 'name' => 'Additional charge per hour',
- 'default' => 0,
- },
- 'recur_hourly_cap' => { 'name' => 'Maximum overage charge for hours'.
- ' (0 means no cap)',
-
- 'default' => 0,
- },
-
- 'recur_included_input' => { 'name' => 'Upload megabytes included',
+ 'recur_included_output' => { 'name' => 'Download megabytes included',
+ 'default' => 0,
+ },
+ 'recur_output_charge' => { 'name' =>
+ 'Additional charge per megabyte download',
'default' => 0,
},
- 'recur_input_charge' => { 'name' =>
- 'Additional charge per megabyte upload',
- 'default' => 0,
- },
- 'recur_input_cap' => { 'name' => 'Maximum overage charge for upload'.
- ' (0 means no cap)',
- 'default' => 0,
- },
-
- 'recur_included_output' => { 'name' => 'Download megabytes included',
- 'default' => 0,
- },
- 'recur_output_charge' => { 'name' =>
- 'Additional charge per megabyte download',
- 'default' => 0,
- },
- 'recur_output_cap' => { 'name' => 'Maximum overage charge for download'.
- ' (0 means no cap)',
- 'default' => 0,
- },
-
- 'recur_included_total' => { 'name' =>
- 'Total megabytes included',
+ 'recur_included_total' => { 'name' =>
+ 'Total megabytes included',
+ 'default' => 0,
+ },
+ 'recur_total_charge' => { 'name' =>
+ 'Additional charge per megabyte total',
'default' => 0,
},
- 'recur_total_charge' => { 'name' =>
- 'Additional charge per megabyte total',
- 'default' => 0,
- },
- 'recur_total_cap' => { 'name' => 'Maximum overage charge for total'.
- ' megabytes (0 means no cap)',
- 'default' => 0,
- },
-
- 'global_cap' => { 'name' => 'Global cap on all overage charges'.
- ' (0 means no cap)',
- 'default' => 0,
- },
-
- },
- 'fieldorder' => [qw( setup_fee recur_flat unused_credit recur_included_hours recur_hourly_charge recur_hourly_cap recur_included_input recur_input_charge recur_input_cap recur_included_output recur_output_charge recur_output_cap recur_included_total recur_total_charge recur_total_cap global_cap )],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $last_bill = $cust_pkg->last_bill; my $hours = $cust_pkg->seconds_since_sqlradacct($last_bill, $sdate ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; my $input = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctInputOctets\" ) / 1048576; my $output = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctOutputOctets\" ) / 1048576; my $total = $input + $output - \' + what.recur_included_total.value + \'; $total = 0 if $total < 0; my $input = $input - \' + what.recur_included_input.value + \'; $input = 0 if $input < 0; my $output = $output - \' + what.recur_included_output.value + \'; $output = 0 if $output < 0; my $totalcharge = sprintf(\"%.2f\", \' + what.recur_total_charge.value + \' * $total); my $inputcharge = sprintf(\"%.2f\", \' + what.recur_input_charge.value + \' * $input); my $outputcharge = sprintf(\"%.2f\", \' + what.recur_output_charge.value + \' * $output); my $hourscharge = sprintf(\"%.2f\", \' + what.recur_hourly_charge.value + \' * $hours); if ( \' + what.recur_total_charge.value + \' > 0 ) { push @details, \"Last month\\\'s data \". sprintf(\"%.1f\", $total). \" megs: \\\$$totalcharge\" } if ( \' + what.recur_input_charge.value + \' > 0 ) { push @details, \"Last month\\\'s download \". sprintf(\"%.1f\", $input). \" megs: \\\$$inputcharge\" } if ( \' + what.recur_output_charge.value + \' > 0 ) { push @details, \"Last month\\\'s upload \". sprintf(\"%.1f\", $output). \" megs: \\\$$outputcharge\" } if ( \' + what.recur_hourly_charge.value + \' > 0 ) { push @details, \"Last month\\\'s time \". sprintf(\"%.1f\", $hours). \" hours: \\\$$hourscharge\"; } \' + what.recur_flat.value + \' + $hourscharge + $inputcharge + $outputcharge + $totalcharge ;\'',
- 'weight' => 40,
+ },
+ 'fieldorder' => [qw( setup_fee recur_flat recur_included_hours recur_hourly_charge recur_included_input recur_input_charge recur_included_output recur_output_charge recur_included_total recur_total_charge )],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $last_bill = $cust_pkg->last_bill; my $hours = $cust_pkg->seconds_since_sqlradacct($last_bill, $sdate ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; my $input = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctInputOctets\" ) / 1048576; my $output = $cust_pkg->attribute_since_sqlradacct($last_bill, $sdate, \"AcctOutputOctets\" ) / 1048576; my $total = $input + $output - \' + what.recur_included_total.value + \'; $total = 0 if $total < 0; my $input = $input - \' + what.recur_included_input.value + \'; $input = 0 if $input < 0; my $output = $output - \' + what.recur_included_output.value + \'; $output = 0 if $output < 0; my $totalcharge = sprintf(\"%.2f\", \' + what.recur_total_charge.value + \' * $total); my $inputcharge = sprintf(\"%.2f\", \' + what.recur_input_charge.value + \' * $input); my $outputcharge = sprintf(\"%.2f\", \' + what.recur_output_charge.value + \' * $output); my $hourscharge = sprintf(\"%.2f\", \' + what.recur_hourly_charge.value + \' * $hours); if ( \' + what.recur_total_charge.value + \' > 0 ) { push @details, \"Last month\\\'s data \". sprintf(\"%.1f\", $total). \" megs: \\\$$totalcharge\" } if ( \' + what.recur_input_charge.value + \' > 0 ) { push @details, \"Last month\\\'s download \". sprintf(\"%.1f\", $input). \" megs: \\\$$inputcharge\" } if ( \' + what.recur_output_charge.value + \' > 0 ) { push @details, \"Last month\\\'s upload \". sprintf(\"%.1f\", $output). \" megs: \\\$$outputcharge\" } if ( \' + what.recur_hourly_charge.value + \' > 0 ) { push @details, \"Last month\\\'s time \". sprintf(\"%.1f\", $hours). \" hours: \\\$$hourscharge\"; } \' + what.recur_flat.value + \' + $hourscharge + $inputcharge + $outputcharge + $totalcharge ;\'',
+ 'weight' => 40,
);
sub calc_recur {
@@ -109,27 +78,13 @@ sub calc_recur {
my $totalcharge =
$total * sprintf('%.2f', $self->option('recur_total_charge'));
- $totalcharge = $self->option('recur_total_cap')
- if $self->option('recur_total_cap')
- && $totalcharge > $self->option('recur_total_cap');
-
my $inputcharge =
$input * sprintf('%.2f', $self->option('recur_input_charge'));
- $inputcharge = $self->option('recur_input_cap')
- if $self->option('recur_input_cap')
- && $inputcharge > $self->option('recur_input_cap');
-
my $outputcharge =
$output * sprintf('%.2f', $self->option('recur_output_charge'));
- $outputcharge = $self->option('recur_output_cap')
- if $self->option('recur_output_cap')
- && $outputcharge > $self->option('recur_output_cap');
my $hourscharge =
$hours * sprintf('%.2f', $self->option('recur_hourly_charge'));
- $hourscharge = $self->option('recur_hours_cap')
- if $self->option('recur_hours_cap')
- && $hourscharge > $self->option('recur_hours_cap');
if ( $self->option('recur_total_charge') > 0 ) {
push @$details, "Last month's data ".
@@ -148,13 +103,8 @@ sub calc_recur {
sprintf('%.1f', $hours). " hours: $hourscharge";
}
- my $charges = $hourscharge + $inputcharge + $outputcharge + $totalcharge;
- if ( $self->option('global_cap') && $charges > $self->option('global_cap') ) {
- $charges = $self->option('global_cap');
- push @$details, "Usage charges capped at: $charges";
- }
-
- $self->option('recur_flat') + $charges;
+ $self->option('recur_flat')
+ + $hourscharge + $inputcharge + $outputcharge + $totalcharge;
}
sub is_free_options {
@@ -162,9 +112,4 @@ sub is_free_options {
recur_input_charge recur_output_charge recur_total_charge );
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_flat');
-}
-
1;
diff --git a/FS/FS/part_pkg/subscription.pm b/FS/FS/part_pkg/subscription.pm
index 36b5a96fb..d057b6b34 100644
--- a/FS/FS/part_pkg/subscription.pm
+++ b/FS/FS/part_pkg/subscription.pm
@@ -4,25 +4,25 @@ use strict;
use vars qw(@ISA %info);
use Time::Local qw(timelocal);
#use FS::Record qw(qsearch qsearchs);
-use FS::part_pkg::flat;
+use FS::part_pkg;
@ISA = qw(FS::part_pkg::flat);
%info = (
- 'name' => 'First partial month full charge, then flat-rate (1st of month billing)',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_fee' => { 'name' => 'Recurring fee for this package',
- 'default' => 0,
- },
- },
- 'fieldorder' => [ 'setup_fee', 'recur_fee' ],
- #'setup' => 'what.setup_fee.value',
- #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; $sdate = timelocal(0,0,0,1,$mon,$year); \' + what.recur_fee.value',
- 'freq' => 'm',
- 'weight' => 30,
+ 'name' => 'First partial month full charge, then flat-rate (1st of month billing)',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_fee' => { 'name' => 'Recurring fee for this package',
+ 'default' => 0,
+ },
+ },
+ 'fieldorder' => [ 'setup_fee', 'recur_fee' ],
+ #'setup' => 'what.setup_fee.value',
+ #'recur' => '\'my $mnow = $sdate; my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($sdate) )[0,1,2,3,4,5]; $sdate = timelocal(0,0,0,1,$mon,$year); \' + what.recur_fee.value',
+ 'freq' => 'm',
+ 'weight' => 30,
);
sub calc_recur {
diff --git a/FS/FS/part_pkg/voip_sqlradacct.pm b/FS/FS/part_pkg/voip_sqlradacct.pm
index fd9c1ddb5..3989cdba6 100644
--- a/FS/FS/part_pkg/voip_sqlradacct.pm
+++ b/FS/FS/part_pkg/voip_sqlradacct.pm
@@ -1,39 +1,32 @@
package FS::part_pkg::voip_sqlradacct;
use strict;
-use vars qw(@ISA $DEBUG %info);
-use Date::Format;
+use vars qw(@ISA %info);
use FS::Record qw(qsearchs qsearch);
-use FS::part_pkg::flat;
+use FS::part_pkg;
#use FS::rate;
use FS::rate_prefix;
-@ISA = qw(FS::part_pkg::flat);
-
-$DEBUG = 1;
+@ISA = qw(FS::part_pkg);
%info = (
- 'name' => 'VoIP rating by plan of CDR records in an SQL RADIUS radacct table',
- 'fields' => {
- 'setup_fee' => { 'name' => 'Setup fee for this package',
- 'default' => 0,
- },
- 'recur_flat' => { 'name' => 'Base recurring fee for this package',
- 'default' => 0,
- },
- 'unused_credit' => { 'name' => 'Credit the customer for the unused portion'.
- ' of service at cancellation',
- 'type' => 'checkbox',
- },
- 'ratenum' => { 'name' => 'Rate plan',
- 'type' => 'select',
- 'select_table' => 'rate',
- 'select_key' => 'ratenum',
- 'select_label' => 'ratename',
- },
- },
- 'fieldorder' => [qw( setup_fee recur_flat unused_credit ratenum ignore_unrateable )],
- 'weight' => 40,
+ 'name' => 'VoIP rating by plan of CDR records in an SQL RADIUS radacct table',
+ 'fields' => {
+ 'setup_fee' => { 'name' => 'Setup fee for this package',
+ 'default' => 0,
+ },
+ 'recur_flat' => { 'name' => 'Base monthly charge for this package',
+ 'default' => 0,
+ },
+ 'ratenum' => { 'name' => 'Rate plan',
+ 'type' => 'select',
+ 'select_table' => 'rate',
+ 'select_key' => 'ratenum',
+ 'select_label' => 'ratename',
+ },
+ },
+ 'fieldorder' => [qw( setup_fee recur_flat ratenum )],
+ 'weight' => 40,
);
sub calc_setup {
@@ -59,10 +52,6 @@ sub calc_recur {
foreach my $session (
$cust_svc->get_session_history( $last_bill, $$sdate )
) {
- if ( $DEBUG > 1 ) {
- warn "rating session $session\n".
- join('', map { " $_ => ". $session->{$_}. "\n" } keys %$session );
- }
###
# look up rate details based on called station id
@@ -74,21 +63,18 @@ sub calc_recur {
$dest =~ s/\s//g;
my $proto = '';
$dest =~ s/^(\w+):// and $proto = $1; #sip:
- my $siphost = '';
- $dest =~ s/\@(.*)$// and $siphost = $1; # @10.54.32.1, @sip.example.com
+ my $ip = '';
+ $dest =~ s/\@((\d{1,3}\.){3}\d{1,3})$// and $ip = $1; # @10.54.32.1
#determine the country code
my $countrycode;
- if ( $dest =~ /^011(((\d)(\d))(\d))(\d+)$/ ) {
-
- my( $three, $two, $one, $u1, $u2, $rest ) = ( $1, $2, $3, $4, $5, $6 );
- #first look for 1 digit country code
- if ( qsearch('rate_prefix', { 'countrycode' => $one } ) ) {
- $countrycode = $one;
- $dest = $u1.$u2.$rest;
- } elsif ( qsearch('rate_prefix', { 'countrycode' => $two } ) ) { #or 2
+ if ( $dest =~ /^011((\d\d)(\d))(\d+)$/ ) {
+
+ my( $three, $two, $unknown, $rest ) = ( $1, $2, $3, $4 );
+ #first look for 2 digit country code
+ if ( qsearch('rate_prefix', { 'countrycode' => $two } ) ) {
$countrycode = $two;
- $dest = $u2.$rest;
+ $dest = $unknown.$rest;
} else { #3 digit country code
$countrycode = $three;
$dest = $rest;
@@ -96,39 +82,31 @@ sub calc_recur {
} else {
$countrycode = '1';
- $dest =~ s/^1//;# if length($dest) > 10;
}
- warn "rating call to +$countrycode $dest\n" if $DEBUG;
-
#find a rate prefix, first look at most specific (4 digits) then 3, etc.,
# finally trying the country code only
my $rate_prefix = '';
- for my $len ( reverse(1..6) ) {
+ for my $len ( reverse(1..4) ) {
$rate_prefix = qsearchs('rate_prefix', {
'countrycode' => $countrycode,
- #'npa' => { op=> 'LIKE', value=> substr($dest, 0, $len) }
- 'npa' => substr($dest, 0, $len),
+ 'npa' => { op=> 'LIKE', value=> substr($dest, 0, $len) }
} ) and last;
}
$rate_prefix ||= qsearchs('rate_prefix', {
'countrycode' => $countrycode,
'npa' => '',
});
-
- die "Can't find rate for call to +$countrycode $dest\n"
+ die "Can't find rate for call to countrycode $countrycode number $dest\n"
unless $rate_prefix;
my $regionnum = $rate_prefix->regionnum;
+
my $rate_detail = qsearchs('rate_detail', {
'ratenum' => $ratenum,
'dest_regionnum' => $regionnum,
} );
- warn " found rate for regionnum $regionnum ".
- "and rate detail $rate_detail\n"
- if $DEBUG;
-
###
# find the price and add detail to the invoice
###
@@ -152,23 +130,16 @@ sub calc_recur {
$charges += $charge;
}
- my $rate_region = $rate_prefix->rate_region;
- warn " (rate region $rate_region)\n" if $DEBUG;
-
- my @call_details = (
- #time2str("%Y %b %d - %r", $session->{'acctstarttime'}),
- time2str("%c", $session->{'acctstarttime'}),
- $minutes.'m',
- '$'.$charge,
- "+$countrycode $dest",
- $rate_region->regionname,
- );
-
- warn " adding details on charge to invoice: ".
- join(' - ', @call_details )
- if $DEBUG;
-
- push @$details, join(' - ', @call_details); #\@call_details,
+ push @$details,
+ #[
+ join(' - ',
+ "+$countrycode $dest",
+ $rate_prefix->rate_region->regionname,
+ $minutes.'m',
+ '$'.$charge,
+ #]
+ )
+ ;
} # $session
@@ -182,10 +153,5 @@ sub is_free {
0;
}
-sub base_recur {
- my($self, $cust_pkg) = @_;
- $self->option('recur_flat');
-}
-
1;
diff --git a/FS/FS/part_svc.pm b/FS/FS/part_svc.pm
index 1a478a9cd..e7f205d10 100644
--- a/FS/FS/part_svc.pm
+++ b/FS/FS/part_svc.pm
@@ -1,9 +1,8 @@
package FS::part_svc;
use strict;
-use vars qw( @ISA $DEBUG );
+use vars qw( @ISA );
use FS::Record qw( qsearch qsearchs fields dbh );
-use FS::Schema qw( dbdef );
use FS::part_svc_column;
use FS::part_export;
use FS::export_svc;
@@ -11,8 +10,6 @@ use FS::cust_svc;
@ISA = qw(FS::Record);
-$DEBUG = 0;
-
=head1 NAME
FS::part_svc - Object methods for part_svc objects
@@ -67,7 +64,7 @@ database, see L<"insert">.
sub table { 'part_svc'; }
-=item insert [ EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF [ , JOB ] ] ]
+=item insert [ EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF ] ]
Adds this service definition to the database. If there is an error, returns
the error, otherwise returns false.
@@ -90,8 +87,6 @@ EXTRA_FIELDS_ARRAYREF also.
If EXPORTNUMS_HASHREF is specified (keys are exportnums and values are
boolean), the appopriate export_svc records will be inserted.
-TODOC: JOB
-
=cut
sub insert {
@@ -103,8 +98,6 @@ sub insert {
my $exportnums = shift;
@exportnums = grep $exportnums->{$_}, keys %$exportnums;
}
- my $job = '';
- $job = shift if @_;
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
@@ -163,14 +156,13 @@ sub insert {
}
# add export_svc records
- my $slice = 100/scalar(@exportnums) if @exportnums;
- my $done = 0;
+
foreach my $exportnum ( @exportnums ) {
my $export_svc = new FS::export_svc ( {
'exportnum' => $exportnum,
'svcpart' => $self->svcpart,
} );
- $error = $export_svc->insert($job, $slice*$done++, $slice);
+ $error = $export_svc->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
@@ -193,7 +185,7 @@ sub delete {
# check & make sure the svcpart isn't in cust_svc or pkg_svc (in any packages)?
}
-=item replace OLD_RECORD [ '1.3-COMPAT' [ , EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF [ , JOB ] ] ] ]
+=item replace OLD_RECORD [ '1.3-COMPAT' [ , EXTRA_FIELDS_ARRAYREF [ , EXPORTNUMS_HASHREF ] ] ]
Replaces OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
@@ -202,26 +194,10 @@ TODOC: 1.3-COMPAT
TODOC: EXTRA_FIELDS_ARRAYREF (same as insert method)
-TODOC: JOB
-
=cut
sub replace {
my ( $new, $old ) = ( shift, shift );
- my $compat = '';
- my @fields = ();
- my $exportnums;
- my $job = '';
- if ( @_ && $_[0] eq '1.3-COMPAT' ) {
- shift;
- $compat = '1.3';
- @fields = @{shift(@_)} if @_;
- $exportnums = @_ ? shift : '';
- $job = shift if @_;
- } else {
- return 'non-1.3-COMPAT interface not yet written';
- #not yet implemented
- }
return "Can't change svcdb for an existing service definition!"
unless $old->svcdb eq $new->svcdb;
@@ -243,7 +219,11 @@ sub replace {
return $error;
}
- if ( $compat eq '1.3' ) {
+ if ( @_ && $_[0] eq '1.3-COMPAT' ) {
+ shift;
+ my @fields = ();
+ @fields = @{shift(@_)} if @_;
+ my $exportnums = @_ ? shift : '';
# maintain part_svc_column records
@@ -284,7 +264,6 @@ sub replace {
if ( $exportnums ) {
#false laziness w/ edit/process/agent_type.cgi
- my @new_export_svc = ();
foreach my $part_export ( qsearch('part_export', {}) ) {
my $exportnum = $part_export->exportnum;
my $hashref = {
@@ -300,26 +279,14 @@ sub replace {
return $error;
}
} elsif ( ! $export_svc && $exportnums->{$exportnum} ) {
- push @new_export_svc, new FS::export_svc ( $hashref );
- }
-
- }
-
- my $slice = 100/scalar(@new_export_svc) if @new_export_svc;
- my $done = 0;
- foreach my $export_svc (@new_export_svc) {
- $error = $export_svc->insert($job, $slice*$done++, $slice);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- if ( $job ) {
- $error = $job->update_statustext( int( $slice * $done ) );
+ $export_svc = new FS::export_svc ( $hashref );
+ $error = $export_svc->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
}
+
}
}
@@ -393,8 +360,8 @@ sub all_part_svc_column {
=item part_export [ EXPORTTYPE ]
-Returns a list of all exports (see L<FS::part_export>) for this service, or,
-if an export type is specified, only returns exports of the given type.
+Returns all exports (see L<FS::part_export>) for this service, or, if an
+export type is specified, only returns exports of the given type.
=cut
@@ -406,85 +373,15 @@ sub part_export {
qsearch('export_svc', { 'svcpart' => $self->svcpart } );
}
-=item part_export_usage
-
-Returns a list of any exports (see L<FS::part_export>) for this service that
-are capable of reporting usage information.
-
-=cut
-
-sub part_export_usage {
- my $self = shift;
- grep $_->can('usage_sessions'), $self->part_export;
-}
-
-=item cust_svc [ PKGPART ]
-
-Returns a list of associated customer services (FS::cust_svc records).
+=item cust_svc
-If a PKGPART is specified, returns the customer services which are contained
-within packages of that type (see L<FS::part_pkg>). If PKGPARTis specified as
-B<0>, returns unlinked customer services.
+Returns a list of associated FS::cust_svc records.
=cut
sub cust_svc {
my $self = shift;
-
- my $hashref = { 'svcpart' => $self->svcpart };
-
- my( $addl_from, $extra_sql ) = ( '', '' );
- if ( @_ ) {
- my $pkgpart = shift;
- if ( $pkgpart =~ /^(\d+)$/ ) {
- $addl_from = 'LEFT JOIN cust_pkg USING ( pkgnum )';
- $extra_sql = "AND pkgpart = $1";
- } elsif ( $pkgpart eq '0' ) {
- $hashref->{'pkgnum'} = '';
- }
- }
-
- qsearch({
- 'table' => 'cust_svc',
- 'addl_from' => $addl_from,
- 'hashref' => $hashref,
- 'extra_sql' => $extra_sql,
- });
-}
-
-=item num_cust_svc [ PKGPART ]
-
-Returns the number of associated customer services (FS::cust_svc records).
-
-If a PKGPART is specified, returns the number of customer services which are
-contained within packages of that type (see L<FS::part_pkg>). If PKGPART
-is specified as B<0>, returns the number of unlinked customer services.
-
-=cut
-
-sub num_cust_svc {
- my $self = shift;
-
- my @param = ( $self->svcpart );
-
- my( $join, $and ) = ( '', '' );
- if ( @_ ) {
- my $pkgpart = shift;
- if ( $pkgpart ) {
- $join = 'LEFT JOIN cust_pkg USING ( pkgnum )';
- $and = 'AND pkgpart = ?';
- push @param, $pkgpart;
- } elsif ( $pkgpart eq '0' ) {
- $and = 'AND pkgnum IS NULL';
- }
- }
-
- my $sth = dbh->prepare(
- "SELECT COUNT(*) FROM cust_svc $join WHERE svcpart = ? $and"
- ) or die dbh->errstr;
- $sth->execute(@param)
- or die $sth->errstr;
- $sth->fetchrow_arrayref->[0];
+ qsearch('cust_svc', { 'svcpart' => $self->svcpart } );
}
=item svc_x
@@ -498,136 +395,8 @@ sub svc_x {
map { $_->svc_x } $self->cust_svc;
}
-
=back
-=head1 SUBROUTINES
-
-=over 4
-
-=item process
-
-Job-queue processor for web interface adds/edits
-
-=cut
-
-use Storable qw(thaw);
-use Data::Dumper;
-use MIME::Base64;
-sub process {
- my $job = shift;
-
- my $param = thaw(decode_base64(shift));
- warn Dumper($param) if $DEBUG;
-
- my $old = qsearchs('part_svc', { 'svcpart' => $param->{'svcpart'} })
- if $param->{'svcpart'};
-
- $param->{'svc_acct__usergroup'} =
- ref($param->{'svc_acct__usergroup'})
- ? join(',', @{$param->{'svc_acct__usergroup'}} )
- : $param->{'svc_acct__usergroup'};
-
- my $new = new FS::part_svc ( {
- map {
- $_ => $param->{$_};
- # } qw(svcpart svc svcdb)
- } ( fields('part_svc'),
- map { my $svcdb = $_;
- my @fields = fields($svcdb);
- push @fields, 'usergroup' if $svcdb eq 'svc_acct'; #kludge
- map { ( $svcdb.'__'.$_, $svcdb.'__'.$_.'_flag' ) } @fields;
- } grep defined( dbdef->table($_) ),
- qw( svc_acct svc_domain svc_forward svc_www svc_broadband )
- )
- } );
-
- my %exportnums =
- map { $_->exportnum => ( $param->{'exportnum'.$_->exportnum} || '') }
- qsearch('part_export', {} );
-
- my $error;
- if ( $param->{'svcpart'} ) {
- $error = $new->replace( $old,
- '1.3-COMPAT',
- [ 'usergroup' ],
- \%exportnums,
- $job
- );
- } else {
- $error = $new->insert( [ 'usergroup' ],
- \%exportnums,
- $job,
- );
- $param->{'svcpart'} = $new->getfield('svcpart');
- }
-
- die "$error\n" if $error;
-}
-
-=item process_bulk_cust_svc
-
-Job-queue processor for web interface bulk customer service changes
-
-=cut
-
-use Storable qw(thaw);
-use Data::Dumper;
-use MIME::Base64;
-sub process_bulk_cust_svc {
- my $job = shift;
-
- my $param = thaw(decode_base64(shift));
- warn Dumper($param) if $DEBUG;
-
- my $old_part_svc =
- qsearchs('part_svc', { 'svcpart' => $param->{'old_svcpart'} } );
-
- die "Must select a new service definition\n" unless $param->{'new_svcpart'};
-
- #the rest should be abstracted out to to its own subroutine?
-
- 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;
-
- local( $FS::cust_svc::ignore_quantity ) = 1;
-
- my $total = $old_part_svc->num_cust_svc( $param->{'pkgpart'} );
-
- my $n = 0;
- foreach my $old_cust_svc ( $old_part_svc->cust_svc( $param->{'pkgpart'} ) ) {
-
- my $new_cust_svc = new FS::cust_svc { $old_cust_svc->hash };
-
- $new_cust_svc->svcpart( $param->{'new_svcpart'} );
- my $error = $new_cust_svc->replace($old_cust_svc);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- die "$error\n" if $error;
- }
-
- $error = $job->update_statustext( int( 100 * ++$n / $total ) );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- die $error if $error;
- }
-
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- '';
-
-}
-
=head1 BUGS
Delete is unimplemented.
@@ -635,7 +404,7 @@ Delete is unimplemented.
The list of svc_* tables is hardcoded. When svc_acct_pop is renamed, this
should be fixed.
-all_part_svc_column methods should be documented
+all_part_svc_column method should be documented
=head1 SEE ALSO
diff --git a/FS/FS/part_svc_router.pm b/FS/FS/part_svc_router.pm
index df04cc9fb..0b23ab580 100755
--- a/FS/FS/part_svc_router.pm
+++ b/FS/FS/part_svc_router.pm
@@ -13,8 +13,7 @@ sub table { 'part_svc_router'; }
sub check {
my $self = shift;
my $error =
- $self->ut_numbern('svcrouternum')
- || $self->ut_foreign_key('svcpart', 'part_svc', 'svcpart')
+ $self->ut_foreign_key('svcpart', 'part_svc', 'svcpart')
|| $self->ut_foreign_key('routernum', 'router', 'routernum');
return $error if $error;
''; #no error
diff --git a/FS/FS/part_virtual_field.pm b/FS/FS/part_virtual_field.pm
index 992d4496e..f6a8fe745 100755
--- a/FS/FS/part_virtual_field.pm
+++ b/FS/FS/part_virtual_field.pm
@@ -2,8 +2,7 @@ package FS::part_virtual_field;
use strict;
use vars qw( @ISA );
-use FS::Record qw( qsearchs qsearch );
-use FS::Schema qw( dbdef );
+use FS::Record qw( qsearchs qsearch dbdef );
@ISA = qw( FS::Record );
@@ -162,7 +161,7 @@ sub check {
# Make sure it's a real table with a numeric primary key
my ($table, $pkey);
- if($table = dbdef->table($self->dbtable)) {
+ if($table = $FS::Record::dbdef->table($self->dbtable)) {
if($pkey = $table->primary_key) {
if($table->column($pkey)->type =~ /int/i) {
# this is what it should be
diff --git a/FS/FS/payment_gateway.pm b/FS/FS/payment_gateway.pm
deleted file mode 100644
index a5cdd9d8d..000000000
--- a/FS/FS/payment_gateway.pm
+++ /dev/null
@@ -1,147 +0,0 @@
-package FS::payment_gateway;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-use FS::option_Common;
-
-@ISA = qw( FS::option_Common );
-
-=head1 NAME
-
-FS::payment_gateway - Object methods for payment_gateway records
-
-=head1 SYNOPSIS
-
- use FS::payment_gateway;
-
- $record = new FS::payment_gateway \%hash;
- $record = new FS::payment_gateway { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::payment_gateway object represents an payment gateway.
-FS::payment_gateway inherits from FS::Record. The following fields are
-currently supported:
-
-=over 4
-
-=item gatewaynum - primary key
-
-=item gateway_module - Business::OnlinePayment:: module name
-
-=item gateway_username - payment gateway username
-
-=item gateway_password - payment gateway password
-
-=item gateway_action - optional action or actions (multiple actions are separated with `,': for example: `Authorization Only, Post Authorization'). Defaults to `Normal Authorization'.
-
-=item disabled - Disabled flag, empty or 'Y'
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new payment gateway. To add the payment gateway 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'payment_gateway'; }
-
-=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 payment gateway. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('gatewaynum')
- || $self->ut_alpha('gateway_module')
- || $self->ut_textn('gateway_username')
- || $self->ut_anything('gateway_password')
- || $self->ut_enum('disabled', [ '', 'Y' ] )
- #|| $self->ut_textn('gateway_action')
- ;
- return $error if $error;
-
- if ( $self->gateway_action ) {
- my @actions = split(/,\s*/, $self->gateway_action);
- $self->gateway_action(
- join( ',', map { /^(Normal Authorization|Authorization Only|Credit|Post Authorization)$/
- or return "Unknown action $_";
- $1
- }
- @actions
- )
- );
- } else {
- $self->gateway_action('Normal Authorization');
- }
-
- $self->SUPER::check;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/payment_gateway_option.pm b/FS/FS/payment_gateway_option.pm
deleted file mode 100644
index 057602291..000000000
--- a/FS/FS/payment_gateway_option.pm
+++ /dev/null
@@ -1,126 +0,0 @@
-package FS::payment_gateway_option;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::payment_gateway_option - Object methods for payment_gateway_option records
-
-=head1 SYNOPSIS
-
- use FS::payment_gateway_option;
-
- $record = new FS::payment_gateway_option \%hash;
- $record = new FS::payment_gateway_option { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::payment_gateway_option object represents an option key and value for
-a payment gateway. FS::payment_gateway_option inherits from
-FS::Record. The following fields are currently supported:
-
-=over 4
-
-=item optionnum - primary key
-
-=item gatewaynum -
-
-=item optionname -
-
-=item optionvalue -
-
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new option. To add the option 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'payment_gateway_option'; }
-
-=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 option. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('optionnum')
- || $self->ut_foreign_key('gatewaynum', 'payment_gateway', 'gatewaynum')
- || $self->ut_text('optionname')
- || $self->ut_textn('optionvalue')
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=back
-
-=head1 BUGS
-
-=head1 SEE ALSO
-
-L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
diff --git a/FS/FS/pkg_svc.pm b/FS/FS/pkg_svc.pm
index 065ddbe51..ea52176cb 100644
--- a/FS/FS/pkg_svc.pm
+++ b/FS/FS/pkg_svc.pm
@@ -39,8 +39,6 @@ FS::Record. The following fields are currently supported:
=over 4
-=item pkgsvcnum - primary key
-
=item pkgpart - Billing item definition (see L<FS::part_pkg>)
=item svcpart - Service definition (see L<FS::part_svc>)
@@ -103,8 +101,7 @@ sub check {
my $error;
$error =
- $self->ut_numbern('pkgsvcnum')
- || $self->ut_number('pkgpart')
+ $self->ut_number('pkgpart')
|| $self->ut_number('svcpart')
|| $self->ut_number('quantity')
;
diff --git a/FS/FS/prepay_credit.pm b/FS/FS/prepay_credit.pm
index 92f2a3032..a9d26d151 100644
--- a/FS/FS/prepay_credit.pm
+++ b/FS/FS/prepay_credit.pm
@@ -2,8 +2,8 @@ package FS::prepay_credit;
use strict;
use vars qw( @ISA );
-use FS::Record qw(qsearchs dbh);
-use FS::agent;
+#use FS::Record qw( qsearch qsearchs );
+use FS::Record qw();
@ISA = qw(FS::Record);
@@ -37,8 +37,8 @@ FS::prepay_credit - Object methods for prepay_credit records
=head1 DESCRIPTION
-An FS::prepay_credit object represents a pre-paid card. FS::prepay_credit
-inherits from FS::Record. The following
+An FS::table_name object represents an pre--paid credit, such as a pre-paid
+"calling card". FS::prepay_credit inherits from FS::Record. The following
fields are currently supported:
=over 4
@@ -51,8 +51,6 @@ fields are currently supported:
=item seconds - time amount of credit (see L<FS::svc_acct/seconds>)
-=item agentnum - optional agent (see L<FS::agent>) for this prepaid card
-
=back
=head1 METHODS
@@ -109,76 +107,14 @@ sub check {
$self->ut_numbern('prepaynum')
|| $self->ut_alpha('identifier')
|| $self->ut_money('amount')
- || $self->ut_numbern('seconds')
- || $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum')
+ || $self->utnumbern('seconds')
|| $self->SUPER::check
;
}
-=item agent
-
-Returns the agent (see L<FS::agent>) for this prepaid card, if any.
-
-=cut
-
-sub agent {
- my $self = shift;
- qsearchs('agent', { 'agentnum' => $self->agentnum } );
-}
-
=back
-=head1 SUBROUTINES
-
-=over 4
-
-=item generate NUM TYPE HASHREF
-
-Generates the specified number of prepaid cards. Returns an array reference of
-the newly generated card identifiers, or a scalar error message.
-
-=cut
-
-#false laziness w/agent::generate_reg_codes
-sub generate {
- my( $num, $type, $hashref ) = @_;
-
- my @codeset = ();
- push @codeset, ( 'A'..'Z' ) if $type =~ /alpha/;
- push @codeset, ( '1'..'9' ) if $type =~ /numeric/;
-
- 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 @cards = ();
- for ( 1 ... $num ) {
- my $prepay_credit = new FS::prepay_credit {
- 'identifier' => join('', map($codeset[int(rand $#codeset)], (0..7) ) ),
- %$hashref,
- };
- my $error = $prepay_credit->check || $prepay_credit->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "(inserting prepay_credit) $error";
- }
- push @cards, $prepay_credit->identifier;
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
-
- \@cards;
-
-}
-
=head1 BUGS
=head1 SEE ALSO
diff --git a/FS/FS/queue.pm b/FS/FS/queue.pm
index f42d99837..dcac3c62b 100644
--- a/FS/FS/queue.pm
+++ b/FS/FS/queue.pm
@@ -3,7 +3,7 @@ package FS::queue;
use strict;
use vars qw( @ISA @EXPORT_OK $DEBUG $conf $jobnums);
use Exporter;
-use FS::UID qw(myconnect);
+use FS::UID;
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh );
#use FS::queue;
@@ -15,6 +15,7 @@ use FS::cust_svc;
@EXPORT_OK = qw( joblisting );
$DEBUG = 0;
+#$DEBUG = 1;
$FS::UID::callback{'FS::queue'} = sub {
$conf = new FS::Conf;
@@ -306,38 +307,6 @@ sub depended_delete {
}
}
-=item update_statustext VALUE
-
-Updates the statustext value of this job to supplied value, in the database.
-If there is an error, returns the error, otherwise returns false.
-
-=cut
-
-use vars qw($_update_statustext_dbh);
-sub update_statustext {
- my( $self, $statustext ) = @_;
- return '' if $statustext eq $self->statustext;
- warn "updating statustext for $self to $statustext" if $DEBUG;
-
- $_update_statustext_dbh ||= myconnect;
-
- my $sth = $_update_statustext_dbh->prepare(
- 'UPDATE queue set statustext = ? WHERE jobnum = ?'
- ) or return $_update_statustext_dbh->errstr;
-
- $sth->execute($statustext, $self->jobnum) or return $sth->errstr;
- $_update_statustext_dbh->commit or die $_update_statustext_dbh->errstr;
- $self->statustext($statustext);
- '';
-
- #my $new = new FS::queue { $self->hash };
- #$new->statustext($statustext);
- #my $error = $new->replace($self);
- #return $error if $error;
- #$self->statustext($statustext);
- #'';
-}
-
=back
=head1 SUBROUTINES
diff --git a/FS/FS/raddb.pm b/FS/FS/raddb.pm
index 506b32568..efeb739bb 100644
--- a/FS/FS/raddb.pm
+++ b/FS/FS/raddb.pm
@@ -2,1910 +2,1597 @@ package FS::raddb;
use vars qw(%attrib);
%attrib = (
- '3com_user_access_level' => '3Com-User-Access-Level',
- '3gpp2_accounting_contain' => '3GPP2-Accounting-Container',
- '3gpp2_acct_stop_trigger' => '3GPP2-Acct-Stop-Trigger',
- '3gpp2_active_time' => '3GPP2-Active-Time',
- '3gpp2_airlink_priority' => '3GPP2-Airlink-Priority',
- '3gpp2_airlink_record_typ' => '3GPP2-Airlink-Record-Type',
- '3gpp2_airlink_sequence_n' => '3GPP2-Airlink-Sequence-Number',
- '3gpp2_allowed_diffserv_m' => '3GPP2-Allowed-Diffserv-Marking',
- '3gpp2_allowed_persistent' => '3GPP2-Allowed-Persistent-TFTs',
- '3gpp2_bad_ppp_frame_coun' => '3GPP2-Bad-PPP-Frame-Count',
- '3gpp2_begin_session' => '3GPP2-Begin-Session',
- '3gpp2_bsid' => '3GPP2-BSID',
- '3gpp2_compulsory_tunnel_' => '3GPP2-Compulsory-Tunnel-Indicator',
- '3gpp2_correlation_id' => '3GPP2-Correlation-Id',
- '3gpp2_dcch_frame_size' => '3GPP2-DCCH-Frame-Size',
- '3gpp2_diffserv_class_opt' => '3GPP2-Diffserv-Class-Option',
- '3gpp2_disconnect_reason' => '3GPP2-Disconnect-Reason',
- '3gpp2_dns_update_capabil' => '3GPP2-DNS-Update-Capability',
- '3gpp2_dns_update_require' => '3GPP2-DNS-Update-Required',
- '3gpp2_esn' => '3GPP2-ESN',
- '3gpp2_fch_frame_size' => '3GPP2-FCH-Frame-Size',
- '3gpp2_foreign_agent_addr' => '3GPP2-Foreign-Agent-Address',
- '3gpp2_forward_dcch_mux_o' => '3GPP2-Forward-DCCH-Mux-Option',
- '3gpp2_forward_dcch_rc' => '3GPP2-Forward-DCCH-RC',
- '3gpp2_forward_fch_mux_op' => '3GPP2-Forward-FCH-Mux-Option',
- '3gpp2_forward_fch_rc' => '3GPP2-Forward-FCH-RC',
- '3gpp2_forward_pdch_rc' => '3GPP2-Forward-PDCH-RC',
- '3gpp2_forward_traffic_ty' => '3GPP2-Forward-Traffic-Type',
- '3gpp2_home_agent_ip_addr' => '3GPP2-Home-Agent-IP-Address',
- '3gpp2_ike_preshared_secr' => '3GPP2-Ike-Preshared-Secret-Request',
- '3gpp2_inbound_mobile_ip_' => '3GPP2-Inbound-Mobile-IP-Sig-Octets',
- '3gpp2_ip_qos' => '3GPP2-IP-QoS',
- '3gpp2_ip_technology' => '3GPP2-IP-Technology',
- '3gpp2_keyid' => '3GPP2-KeyID',
- '3gpp2_last_user_activity' => '3GPP2-Last-User-Activity-Time',
- '3gpp2_mip_lifetime' => '3GPP2-MIP-Lifetime',
- '3gpp2_mn_aaa_removal_ind' => '3GPP2-MN-AAA-Removal-Indication',
- '3gpp2_mn_ha_shared_key' => '3GPP2-MN-HA-Shared-Key',
- '3gpp2_mn_ha_spi' => '3GPP2-MN-HA-SPI',
- '3gpp2_module_orig_term_i' => '3GPP2-Module-Orig-Term-Indicator',
- '3gpp2_number_active_tran' => '3GPP2-Number-Active-Transitions',
- '3gpp2_originating_number' => '3GPP2-Originating-Number-SDBs',
- '3gpp2_originating_sdb_oc' => '3GPP2-Originating-SDB-OCtet-Count',
- '3gpp2_outbound_mobile_ip' => '3GPP2-Outbound-Mobile-IP-Sig-Octets',
- '3gpp2_pcf_ip_address' => '3GPP2-PCF-IP-Address',
- '3gpp2_pre_shared_secret' => '3GPP2-Pre-Shared-Secret',
- '3gpp2_prepaid_acct_capab' => '3GPP2-Prepaid-acct-Capability',
- '3gpp2_prepaid_acct_quota' => '3GPP2-Prepaid-Acct-Quota',
- '3gpp2_prepaid_tariff_swi' => '3GPP2-PrePaid-Tariff-Switching',
- '3gpp2_received_hdlc_octe' => '3GPP2-Received-HDLC-Octets',
- '3gpp2_release_indicator' => '3GPP2-Release-Indicator',
- '3gpp2_remote_address_tab' => '3GPP2-Remote-Address-Table-Index',
- '3gpp2_remote_ip_address' => '3GPP2-Remote-IP-Address',
- '3gpp2_remote_ipv4_addr_o' => '3GPP2-Remote-IPv4-Addr-Octet-Count',
- '3gpp2_remote_ipv6_addres' => '3GPP2-Remote-IPv6-Address',
- '3gpp2_remote_ipv6_octet_' => '3GPP2-Remote-IPv6-Octet-Count',
- '3gpp2_reverse_dcch_mux_o' => '3GPP2-Reverse-DCCH-Mux-Option',
- '3gpp2_reverse_dhhc_rc' => '3GPP2-Reverse-DHHC-RC',
- '3gpp2_reverse_fch_mux_op' => '3GPP2-Reverse-FCH-Mux-Option',
- '3gpp2_reverse_fch_rc' => '3GPP2-Reverse-FCH-RC',
- '3gpp2_reverse_traffic_ty' => '3GPP2-Reverse-Traffic-Type',
- '3gpp2_reverse_tunnel_spe' => '3GPP2-Reverse-Tunnel-Spec',
- '3gpp2_rn_packet_data_ina' => '3GPP2-RN-Packet-Data-Inactivity-Timer',
- '3gpp2_s_key' => '3GPP2-S-Key',
- '3gpp2_s_lifetime' => '3GPP2-S-Lifetime',
- '3gpp2_s_request' => '3GPP2-S-Request',
- '3gpp2_security_level' => '3GPP2-Security-Level',
- '3gpp2_service_option' => '3GPP2-Service-Option',
- '3gpp2_service_option_pro' => '3GPP2-Service-Option-Profile',
- '3gpp2_service_reference_' => '3GPP2-Service-Reference-Id',
- '3gpp2_session_continue' => '3GPP2-Session-Continue',
- '3gpp2_session_terminatio' => '3GPP2-Session-Termination-Capability',
- '3gpp2_terminating_number' => '3GPP2-Terminating-Number-SDBs',
- '3gpp2_terminating_sdb_oc' => '3GPP2-Terminating-SDB-Octet-Count',
- '3gpp2_user_id' => '3GPP2-User-Id',
- '3gpp_charging_characteri' => '3GPP-Charging-Characteristics',
- '3gpp_charging_gateway_ad' => '3GPP-Charging-Gateway-Address',
- '3gpp_charging_gateway_ip' => '3GPP-Charging-Gateway-IPv6-Address',
- '3gpp_charging_id' => '3GPP-Charging-ID',
- '3gpp_ggsn_address' => '3GPP-GGSN-Address',
- '3gpp_ggsn_ipv6_address' => '3GPP-GGSN-IPv6-Address',
- '3gpp_ggsn_mcc_mnc' => '3GPP-GGSN-MCC-MNC',
- '3gpp_gprs_negotiated_qos' => '3GPP-GPRS-Negotiated-QoS-profile',
- '3gpp_imsi' => '3GPP-IMSI',
- '3gpp_imsi_mcc_mnc' => '3GPP-IMSI-MCC-MNC',
- '3gpp_ipv6_dns_servers' => '3GPP-IPv6-DNS-Servers',
- '3gpp_nsapi' => '3GPP-NSAPI',
- '3gpp_pdp_type' => '3GPP-PDP-Type',
- '3gpp_selection_mode' => '3GPP-Selection-Mode',
- '3gpp_session_stop_indica' => '3GPP-Session-Stop-Indicator',
- '3gpp_sgsn_address' => '3GPP-SGSN-Address',
- '3gpp_sgsn_ipv6_address' => '3GPP-SGSN-IPv6-Address',
- 'aat_assign_ip_pool' => 'AAT-Assign-IP-Pool',
- 'aat_atm_direct' => 'AAT-ATM-Direct',
- 'aat_atm_traffic_profile' => 'AAT-ATM-Traffic-Profile',
- 'aat_atm_vci' => 'AAT-ATM-VCI',
- 'aat_atm_vpi' => 'AAT-ATM-VPI',
- 'aat_client_primary_dns' => 'AAT-Client-Primary-DNS',
- 'aat_client_primary_wins_' => 'AAT-Client-Primary-WINS-NBNS',
- 'aat_client_secondary_win' => 'AAT-Client-Secondary-WINS-NBNS',
- 'aat_data_filter' => 'AAT-Data-Filter',
- 'aat_input_octets_diff' => 'AAT-Input-Octets-Diff',
- 'aat_ip_pool_definition' => 'AAT-IP-Pool-Definition',
- 'aat_ip_tos' => 'AAT-IP-TOS',
- 'aat_ip_tos_apply_to' => 'AAT-IP-TOS-Apply-To',
- 'aat_ip_tos_precedence' => 'AAT-IP-TOS-Precedence',
- 'aat_mcast_client' => 'AAT-MCast-Client',
- 'aat_output_octets_diff' => 'AAT-Output-Octets-Diff',
- 'aat_ppp_address' => 'AAT-PPP-Address',
- 'aat_require_auth' => 'AAT-Require-Auth',
- 'aat_source_ip_check' => 'AAT-Source-IP-Check',
- 'aat_user_mac_address' => 'AAT-User-MAC-Address',
- 'aat_vrouter_name' => 'AAT-Vrouter-Name',
- 'acc_access_community' => 'Acc-Access-Community',
- 'acc_access_partition' => 'Acc-Access-Partition',
- 'acc_acct_on_off_reason' => 'Acc-Acct-On-Off-Reason',
- 'acc_ace_token' => 'Acc-Ace-Token',
- 'acc_ace_token_ttl' => 'Acc-Ace-Token-Ttl',
- 'acc_apsm_oversubscribed' => 'Acc-Apsm-Oversubscribed',
- 'acc_bridging_support' => 'Acc-Bridging-Support',
- 'acc_callback_cbcp_type' => 'Acc-Callback-CBCP-Type',
- 'acc_callback_delay' => 'Acc-Callback-Delay',
- 'acc_callback_mode' => 'Acc-Callback-Mode',
- 'acc_callback_num_valid' => 'Acc-Callback-Num-Valid',
- 'acc_ccp_option' => 'Acc-Ccp-Option',
- 'acc_clearing_cause' => 'Acc-Clearing-Cause',
- 'acc_clearing_location' => 'Acc-Clearing-Location',
- 'acc_connect_rx_speed' => 'Acc-Connect-Rx-Speed',
- 'acc_connect_tx_speed' => 'Acc-Connect-Tx-Speed',
- 'acc_customer_id' => 'Acc-Customer-Id',
- 'acc_dial_port_index' => 'Acc-Dial-Port-Index',
- 'acc_dialout_auth_mode' => 'Acc-Dialout-Auth-Mode',
- 'acc_dialout_auth_passwor' => 'Acc-Dialout-Auth-Password',
- 'acc_dialout_auth_usernam' => 'Acc-Dialout-Auth-Username',
- 'acc_dns_server_pri' => 'Acc-Dns-Server-Pri',
- 'acc_dns_server_sec' => 'Acc-Dns-Server-Sec',
- 'acc_igmp_admin_state' => 'Acc-Igmp-Admin-State',
- 'acc_igmp_version' => 'Acc-Igmp-Version',
- 'acc_input_errors' => 'Acc-Input-Errors',
- 'acc_ip_compression' => 'Acc-Ip-Compression',
- 'acc_ip_gateway_pri' => 'Acc-Ip-Gateway-Pri',
- 'acc_ip_gateway_sec' => 'Acc-Ip-Gateway-Sec',
- 'acc_ip_pool_name' => 'Acc-Ip-Pool-Name',
- 'acc_ipx_compression' => 'Acc-Ipx-Compression',
- 'acc_ml_call_threshold' => 'Acc-ML-Call-Threshold',
- 'acc_ml_clear_threshold' => 'Acc-ML-Clear-Threshold',
- 'acc_ml_damping_factor' => 'Acc-ML-Damping-Factor',
- 'acc_ml_mlx_admin_state' => 'Acc-ML-MLX-Admin-State',
- 'acc_modem_error_protocol' => 'Acc-Modem-Error-Protocol',
- 'acc_modem_modulation_typ' => 'Acc-Modem-Modulation-Type',
- 'acc_nbns_server_pri' => 'Acc-Nbns-Server-Pri',
- 'acc_nbns_server_sec' => 'Acc-Nbns-Server-Sec',
- 'acc_output_errors' => 'Acc-Output-Errors',
- 'acc_reason_code' => 'Acc-Reason-Code',
- 'acc_request_type' => 'Acc-Request-Type',
- 'acc_route_policy' => 'Acc-Route-Policy',
- 'acc_service_profile' => 'Acc-Service-Profile',
- 'acc_tunnel_port' => 'Acc-Tunnel-Port',
- 'acc_tunnel_secret' => 'Acc-Tunnel-Secret',
- 'acc_vpsm_reject_cause' => 'Acc-Vpsm-Reject-Cause',
- 'acct_authentic' => 'Acct-Authentic',
- 'acct_delay_time' => 'Acct-Delay-Time',
- 'acct_dyn_ac_ent' => 'Acct_Dyn_Ac_Ent',
- 'acct_dyn_ac_enu' => 'Acct-Dyn-Ac-Ent',
- 'acct_input_gigawords' => 'Acct-Input-Gigawords',
- 'acct_input_octets' => 'Acct-Input-Octets',
- 'acct_input_octets_64' => 'Acct_Input_Octets_64',
- 'acct_input_octets_65' => 'Acct-Input-Octets-64',
- 'acct_input_packets' => 'Acct-Input-Packets',
- 'acct_input_packets_64' => 'Acct_Input_Packets_64',
- 'acct_input_packets_65' => 'Acct-Input-Packets-64',
- 'acct_interim_interval' => 'Acct-Interim-Interval',
- 'acct_link_count' => 'Acct-Link-Count',
- 'acct_mcast_in_octets' => 'Acct_Mcast_In_Octets',
- 'acct_mcast_in_octett' => 'Acct-Mcast-In-Octets',
- 'acct_mcast_in_packets' => 'Acct_Mcast_In_Packets',
- 'acct_mcast_in_packett' => 'Acct-Mcast-In-Packets',
- 'acct_mcast_out_octets' => 'Acct_Mcast_Out_Octets',
- 'acct_mcast_out_octett' => 'Acct-Mcast-Out-Octets',
- 'acct_mcast_out_packets' => 'Acct_Mcast_Out_Packets',
- 'acct_mcast_out_packett' => 'Acct-Mcast-Out-Packets',
- 'acct_multi_session_id' => 'Acct-Multi-Session-Id',
- 'acct_output_gigawords' => 'Acct-Output-Gigawords',
- 'acct_output_octets' => 'Acct-Output-Octets',
- 'acct_output_octets_64' => 'Acct_Output_Octets_64',
- 'acct_output_octets_65' => 'Acct-Output-Octets-64',
- 'acct_output_packets' => 'Acct-Output-Packets',
- 'acct_output_packets_64' => 'Acct_Output_Packets_64',
- 'acct_output_packets_65' => 'Acct-Output-Packets-64',
- 'acct_session_gigawords' => 'Acct-Session-Gigawords',
- 'acct_session_id' => 'Acct-Session-Id',
- 'acct_session_input_gigaw' => 'Acct-Session-Input-Gigawords',
- 'acct_session_input_octet' => 'Acct-Session-Input-Octets',
- 'acct_session_octets' => 'Acct-Session-Octets',
- 'acct_session_output_giga' => 'Acct-Session-Output-Gigawords',
- 'acct_session_output_octe' => 'Acct-Session-Output-Octets',
- 'acct_session_start_time' => 'Acct-Session-Start-Time',
- 'acct_session_time' => 'Acct-Session-Time',
- 'acct_status_type' => 'Acct-Status-Type',
- 'acct_terminate_cause' => 'Acct-Terminate-Cause',
- 'acct_tunnel_connection' => 'Acct-Tunnel-Connection',
- 'acct_tunnel_packets_lost' => 'Acct-Tunnel-Packets-Lost',
- 'acct_type' => 'Acct-Type',
- 'acct_unique_session_id' => 'Acct-Unique-Session-Id',
- 'add_prefix' => 'Add-Prefix',
- 'add_suffix' => 'Add-Suffix',
- 'alteon_service_type' => 'Alteon-Service-Type',
- 'altiga_access_hours_g_u' => 'Altiga-Access-Hours-G/U',
- 'altiga_allow_alpha_only_' => 'Altiga-Allow-Alpha-Only-Passwords-G',
- 'altiga_ipsec_allow_passw' => 'Altiga-IPSec-Allow-Passwd-Store-G/U',
- 'altiga_ipsec_authenticat' => 'Altiga-IPSec-Authentication-G',
- 'altiga_ipsec_banner_g' => 'Altiga-IPSec-Banner-G',
- 'altiga_ipsec_default_dom' => 'Altiga-IPSec-Default-Domain-G',
- 'altiga_ipsec_l2l_keepali' => 'Altiga-IPSec-L2L-Keepalives-G',
- 'altiga_ipsec_mode_config' => 'Altiga-IPSec-Mode-Config-G',
- 'altiga_ipsec_over_nat_g' => 'Altiga-IPSec-Over-NAT-G',
- 'altiga_ipsec_over_nat_po' => 'Altiga-IPSec-Over-NAT-Port-Num-G',
- 'altiga_ipsec_sec_associa' => 'Altiga-IPSec-Sec-Association-G/U',
- 'altiga_ipsec_secondary_d' => 'Altiga-IPSec-Secondary-Domains-G',
- 'altiga_ipsec_split_tunne' => 'Altiga-IPSec-Split-Tunnel-List-G',
- 'altiga_ipsec_tunnel_type' => 'Altiga-IPSec-Tunnel-Type-G',
- 'altiga_ipsec_user_group_' => 'Altiga-IPSec-User-Group-Lock-G',
- 'altiga_l2tp_encryption_g' => 'Altiga-L2TP-Encryption-G',
- 'altiga_l2tp_min_authenti' => 'Altiga-L2TP-Min-Authentication-G/U',
- 'altiga_min_password_leng' => 'Altiga-Min-Password-Length-G',
- 'altiga_pptp_encryption_g' => 'Altiga-PPTP-Encryption-G',
- 'altiga_pptp_min_authenti' => 'Altiga-PPTP-Min-Authentication-G/U',
- 'altiga_primary_dns_g' => 'Altiga-Primary-DNS-G',
- 'altiga_primary_wins_g' => 'Altiga-Primary-WINS-G',
- 'altiga_priority_on_sep_g' => 'Altiga-Priority-on-SEP-G/U',
- 'altiga_secondary_dns_g' => 'Altiga-Secondary-DNS-G',
- 'altiga_secondary_wins_g' => 'Altiga-Secondary-WINS-G',
- 'altiga_sep_card_assignme' => 'Altiga-SEP-Card-Assignment-G/U',
- 'altiga_simultaneous_logi' => 'Altiga-Simultaneous-Logins-G/U',
- 'altiga_tunneling_protoco' => 'Altiga-Tunneling-Protocols-G/U',
- 'altiga_use_client_addres' => 'Altiga-Use-Client-Address-G/U',
- 'annex_acct_servers' => 'Annex-Acct-Servers',
- 'annex_addr_resolution_pr' => 'Annex-Addr-Resolution-Protocol',
- 'annex_addr_resolution_se' => 'Annex-Addr-Resolution-Servers',
- 'annex_audit_level' => 'Annex-Audit-Level',
- 'annex_authen_servers' => 'Annex-Authen-Servers',
- 'annex_begin_modulation' => 'Annex-Begin-Modulation',
- 'annex_begin_receive_line' => 'Annex-Begin-Receive-Line-Level',
- 'annex_callback_portlist' => 'Annex-Callback-Portlist',
- 'annex_cli_command' => 'Annex-CLI-Command',
- 'annex_cli_filter' => 'Annex-CLI-Filter',
+ 'usr_at_zip_output_filter' => 'USR-AT-Zip-Output-Filter',
+ 'ms_filter' => 'MS-Filter',
'annex_compression_protoc' => 'Annex-Compression-Protocol',
- 'annex_connect_progress' => 'Annex-Connect-Progress',
- 'annex_disconnect_reason' => 'Annex-Disconnect-Reason',
- 'annex_domain_name' => 'Annex-Domain-Name',
- 'annex_edo' => 'Annex-EDO',
- 'annex_end_modulation' => 'Annex-End-Modulation',
- 'annex_end_receive_line_l' => 'Annex-End-Receive-Line-Level',
+ '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',
+ 'ascend_route_ipx' => 'Ascend-Route-IPX',
'annex_error_correction_p' => 'Annex-Error-Correction-Prot',
- 'annex_filter' => 'Annex-Filter',
- 'annex_host_allow' => 'Annex-Host-Allow',
- 'annex_host_restrict' => 'Annex-Host-Restrict',
- 'annex_input_filter' => 'Annex-Input-Filter',
- 'annex_keypress_timeout' => 'Annex-Keypress-Timeout',
- 'annex_local_ip_address' => 'Annex-Local-IP-Address',
- 'annex_local_username' => 'Annex-Local-Username',
- 'annex_logical_channel_nu' => 'Annex-Logical-Channel-Number',
- 'annex_maximum_call_durat' => 'Annex-Maximum-Call-Duration',
- 'annex_modem_disc_reason' => 'Annex-Modem-Disc-Reason',
- 'annex_mrru' => 'Annex-MRRU',
- 'annex_multicast_rate_lim' => 'Annex-Multicast-Rate-Limit',
- 'annex_multilink_id' => 'Annex-Multilink-Id',
- 'annex_num_in_multilink' => 'Annex-Num-In-Multilink',
- 'annex_output_filter' => 'Annex-Output-Filter',
- 'annex_pool_id' => 'Annex-Pool-Id',
- 'annex_port' => 'Annex-Port',
- 'annex_ppp_trace_level' => 'Annex-PPP-Trace-Level',
- 'annex_pre_input_octets' => 'Annex-Pre-Input-Octets',
- 'annex_pre_input_packets' => 'Annex-Pre-Input-Packets',
- 'annex_pre_output_octets' => 'Annex-Pre-Output-Octets',
- 'annex_pre_output_packets' => 'Annex-Pre-Output-Packets',
- 'annex_primary_dns_server' => 'Annex-Primary-DNS-Server',
- 'annex_primary_nbns_serve' => 'Annex-Primary-NBNS-Server',
- 'annex_product_name' => 'Annex-Product-Name',
- 'annex_rate_reneg_req_rcv' => 'Annex-Rate-Reneg-Req-Rcvd',
- 'annex_rate_reneg_req_sen' => 'Annex-Rate-Reneg-Req-Sent',
- 'annex_re_chap_timeout' => 'Annex-Re-CHAP-Timeout',
- 'annex_receive_speed' => 'Annex-Receive-Speed',
- 'annex_retrain_requests_r' => 'Annex-Retrain-Requests-Rcvd',
- 'annex_retrain_requests_s' => 'Annex-Retrain-Requests-Sent',
- 'annex_retransmitted_pack' => 'Annex-Retransmitted-Packets',
- 'annex_sec_profile_index' => 'Annex-Sec-Profile-Index',
- 'annex_secondary_dns_serv' => 'Annex-Secondary-DNS-Server',
- 'annex_secondary_nbns_ser' => 'Annex-Secondary-NBNS-Server',
- 'annex_signal_to_noise_ra' => 'Annex-Signal-to-Noise-Ratio',
- 'annex_sw_version' => 'Annex-SW-Version',
- 'annex_syslog_tap' => 'Annex-Syslog-Tap',
+ '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',
+ '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',
- 'annex_transmit_speed' => 'Annex-Transmit-Speed',
- 'annex_transmitted_packet' => 'Annex-Transmitted-Packets',
- 'annex_tunnel_authen_mode' => 'Annex-Tunnel-Authen-Mode',
- 'annex_tunnel_authen_type' => 'Annex-Tunnel-Authen-Type',
- 'annex_unauthenticated_ti' => 'Annex-Unauthenticated-Time',
- 'annex_user_level' => 'Annex-User-Level',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'session_error_codf' => 'Session_Error_Code',
'annex_user_server_locati' => 'Annex-User-Server-Location',
- 'annex_wan_number' => 'Annex-Wan-Number',
- 'arap_challenge_response' => 'ARAP-Challenge-Response',
- 'arap_features' => 'ARAP-Features',
- 'arap_password' => 'ARAP-Password',
- 'arap_security' => 'ARAP-Security',
- 'arap_security_data' => 'ARAP-Security-Data',
- 'arap_zone_access' => 'ARAP-Zone-Access',
- 'ascend_access_intercept_' => 'Ascend-Access-Intercept-LEA',
- 'ascend_access_intercepta' => 'Ascend-Access-Intercept-Log',
- 'ascend_add_seconds' => 'Ascend-Add-Seconds',
- 'ascend_appletalk_peer_mo' => 'Ascend-Appletalk-Peer-Mode',
- 'ascend_appletalk_route' => 'Ascend-Appletalk-Route',
- 'ascend_ara_pw' => 'Ascend-Ara-PW',
- 'ascend_assign_ip_client' => 'Ascend-Assign-IP-Client',
- 'ascend_assign_ip_global_' => 'Ascend-Assign-IP-Global-Pool',
- 'ascend_assign_ip_pool' => 'Ascend-Assign-IP-Pool',
- 'ascend_assign_ip_server' => 'Ascend-Assign-IP-Server',
- 'ascend_atm_connect_group' => 'Ascend-ATM-Connect-Group',
- 'ascend_atm_connect_vci' => 'Ascend-ATM-Connect-Vci',
- 'ascend_atm_connect_vpi' => 'Ascend-ATM-Connect-Vpi',
- 'ascend_atm_direct' => 'Ascend-ATM-Direct',
- 'ascend_atm_direct_profil' => 'Ascend-ATM-Direct-Profile',
- 'ascend_atm_fault_managem' => 'Ascend-ATM-Fault-Management',
- 'ascend_atm_group' => 'Ascend-ATM-Group',
- 'ascend_atm_loopback_cell' => 'Ascend-ATM-Loopback-Cell-Loss',
- 'ascend_atm_vci' => 'Ascend-ATM-Vci',
- 'ascend_atm_vpi' => 'Ascend-ATM-Vpi',
- 'ascend_auth_delay' => 'Ascend-Auth-Delay',
- 'ascend_auth_type' => 'Ascend-Auth-Type',
- 'ascend_authen_alias' => 'Ascend-Authen-Alias',
- 'ascend_backup' => 'Ascend-Backup',
- 'ascend_bacp_enable' => 'Ascend-BACP-Enable',
- 'ascend_base_channel_coun' => 'Ascend-Base-Channel-Count',
- 'ascend_bi_directional_au' => 'Ascend-Bi-Directional-Auth',
- 'ascend_billing_number' => 'Ascend-Billing-Number',
- 'ascend_bir_bridge_group' => 'Ascend-BIR-Bridge-Group',
- 'ascend_bir_enable' => 'Ascend-BIR-Enable',
- 'ascend_bir_proxy' => 'Ascend-BIR-Proxy',
- 'ascend_bridge' => 'Ascend-Bridge',
- 'ascend_bridge_address' => 'Ascend-Bridge-Address',
- 'ascend_bridge_non_pppoe' => 'Ascend-Bridge-Non-PPPoE',
- 'ascend_cache_refresh' => 'Ascend-Cache-Refresh',
- 'ascend_cache_time' => 'Ascend-Cache-Time',
- 'ascend_call_attempt_limi' => 'Ascend-Call-Attempt-Limit',
- 'ascend_call_block_durati' => 'Ascend-Call-Block-Duration',
- 'ascend_call_by_call' => 'Ascend-Call-By-Call',
- 'ascend_call_direction' => 'Ascend-Call-Direction',
- 'ascend_call_filter' => 'Ascend-Call-Filter',
- 'ascend_call_type' => 'Ascend-Call-Type',
- 'ascend_callback' => 'Ascend-Callback',
- 'ascend_callback_delay' => 'Ascend-Callback-Delay',
- 'ascend_calling_id_number' => 'Ascend-Calling-Id-Number-Plan',
- 'ascend_calling_id_presen' => 'Ascend-Calling-Id-Presentatn',
- 'ascend_calling_id_screen' => 'Ascend-Calling-Id-Screening',
- 'ascend_calling_id_type_o' => 'Ascend-Calling-Id-Type-Of-Num',
+ 'cisco_fax_mdn_address' => 'Cisco-Fax-Mdn-Address',
'ascend_calling_subaddres' => 'Ascend-Calling-Subaddress',
- 'ascend_cbcp_delay' => 'Ascend-CBCP-Delay',
- 'ascend_cbcp_enable' => 'Ascend-CBCP-Enable',
- 'ascend_cbcp_mode' => 'Ascend-CBCP-Mode',
- 'ascend_cbcp_trunk_group' => 'Ascend-CBCP-Trunk-Group',
- 'ascend_cir_timer' => 'Ascend-CIR-Timer',
- 'ascend_ckt_type' => 'Ascend-Ckt-Type',
- 'ascend_client_assign_dns' => 'Ascend-Client-Assign-DNS',
- 'ascend_client_assign_win' => 'Ascend-Client-Assign-WINS',
- 'ascend_client_gateway' => 'Ascend-Client-Gateway',
- 'ascend_client_primary_dn' => 'Ascend-Client-Primary-DNS',
- 'ascend_client_primary_wi' => 'Ascend-Client-Primary-WINS',
- 'ascend_client_secondary_' => 'Ascend-Client-Secondary-WINS',
- 'ascend_client_secondarya' => 'Ascend-Client-Secondary-DNS',
- 'ascend_connect_progress' => 'Ascend-Connect-Progress',
- 'ascend_data_filter' => 'Ascend-Data-Filter',
- 'ascend_data_rate' => 'Ascend-Data-Rate',
- 'ascend_data_svc' => 'Ascend-Data-Svc',
- 'ascend_dba_monitor' => 'Ascend-DBA-Monitor',
- 'ascend_dec_channel_count' => 'Ascend-Dec-Channel-Count',
- 'ascend_destination_nas_p' => 'Ascend-Destination-Nas-Port',
+ 'ascend_call_by_call' => 'Ascend-Call-By-Call',
+ 'ascend_first_dest' => 'Ascend-First-Dest',
+ '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',
+ 'login_tcp_port' => 'Login-TCP-Port',
+ 'ascend_temporary_rtes' => 'Ascend-Temporary-Rtes',
+ 'versanet_termination_cau' => 'Versanet-Termination-Cause',
+ 'ascend_dialed_number' => 'Ascend-Dialed-Number',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'cisco_avpair' => 'Cisco-AVPair',
+ 'st_service_name' => 'ST-Service-Name',
+ 'shiva_event_flags' => 'Shiva-Event-Flags',
+ 'annex_retrain_requests_s' => 'Annex-Retrain-Requests-Sent',
+ 'ascend_ts_idle_mode' => 'Ascend-TS-Idle-Mode',
+ '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_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',
+ '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_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',
+ 'tunnel_session_auth_serw' => 'Tunnel_Session_Auth_Service_Grp',
+ 'ms_chap2_cpw' => 'MS-CHAP2-CPW',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'usr_device_connected_to' => 'USR-Device-Connected-To',
+ 'aat_source_ip_check' => 'AAT-Source-IP-Check',
+ 'login_lat_service' => 'Login-LAT-Service',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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_igmp_admin_state' => 'Acc-Igmp-Admin-State',
+ 'ascend_host_info' => 'Ascend-Host-Info',
'ascend_dhcp_maximum_leas' => 'Ascend-DHCP-Maximum-Leases',
- 'ascend_dhcp_pool_number' => 'Ascend-DHCP-Pool-Number',
- 'ascend_dhcp_reply' => 'Ascend-DHCP-Reply',
- 'ascend_dial_number' => 'Ascend-Dial-Number',
- 'ascend_dialed_number' => 'Ascend-Dialed-Number',
- 'ascend_dialout_allowed' => 'Ascend-Dialout-Allowed',
- 'ascend_disconnect_cause' => 'Ascend-Disconnect-Cause',
- 'ascend_dropped_octets' => 'Ascend-Dropped-Octets',
- 'ascend_dropped_packets' => 'Ascend-Dropped-Packets',
- 'ascend_dsl_cir_recv_limi' => 'Ascend-Dsl-CIR-Recv-Limit',
- 'ascend_dsl_cir_xmit_limi' => 'Ascend-Dsl-CIR-Xmit-Limit',
- 'ascend_dsl_downstream_li' => 'Ascend-Dsl-Downstream-Limit',
- 'ascend_dsl_rate_mode' => 'Ascend-Dsl-Rate-Mode',
- 'ascend_dsl_rate_type' => 'Ascend-Dsl-Rate-Type',
- 'ascend_dsl_upstream_limi' => 'Ascend-Dsl-Upstream-Limit',
- 'ascend_egress_enabled' => 'Ascend-Egress-Enabled',
- 'ascend_endpoint_disc' => 'Ascend-Endpoint-Disc',
- 'ascend_event_type' => 'Ascend-Event-Type',
- 'ascend_expect_callback' => 'Ascend-Expect-Callback',
- 'ascend_fcp_parameter' => 'Ascend-FCP-Parameter',
- 'ascend_filter' => 'Ascend-Filter',
- 'ascend_filter_required' => 'Ascend-Filter-Required',
- 'ascend_first_dest' => 'Ascend-First-Dest',
- 'ascend_force_56' => 'Ascend-Force-56',
- 'ascend_fr_08_mode' => 'Ascend-FR-08-Mode',
- 'ascend_fr_circuit_name' => 'Ascend-FR-Circuit-Name',
- 'ascend_fr_dce_n392' => 'Ascend-FR-DCE-N392',
- 'ascend_fr_dce_n393' => 'Ascend-FR-DCE-N393',
- 'ascend_fr_direct' => 'Ascend-FR-Direct',
- 'ascend_fr_direct_dlci' => 'Ascend-FR-Direct-DLCI',
+ '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',
- 'ascend_fr_dlci' => 'Ascend-FR-DLCI',
- 'ascend_fr_dte_n392' => 'Ascend-FR-DTE-N392',
- 'ascend_fr_dte_n393' => 'Ascend-FR-DTE-N393',
- 'ascend_fr_link_mgt' => 'Ascend-FR-Link-Mgt',
- 'ascend_fr_link_status_dl' => 'Ascend-FR-Link-Status-DLCI',
- 'ascend_fr_linkup' => 'Ascend-FR-LinkUp',
- 'ascend_fr_n391' => 'Ascend-FR-N391',
- 'ascend_fr_nailed_grp' => 'Ascend-FR-Nailed-Grp',
- 'ascend_fr_profile_name' => 'Ascend-FR-Profile-Name',
- 'ascend_fr_svc_addr' => 'Ascend-FR-SVC-Addr',
- 'ascend_fr_t391' => 'Ascend-FR-T391',
- 'ascend_fr_t392' => 'Ascend-FR-T392',
- 'ascend_fr_type' => 'Ascend-FR-Type',
- 'ascend_ft1_caller' => 'Ascend-FT1-Caller',
- 'ascend_global_call_id' => 'Ascend-Global-Call-Id',
- 'ascend_group' => 'Ascend-Group',
- 'ascend_h323_conference_i' => 'Ascend-H323-Conference-Id',
- 'ascend_h323_dialed_time' => 'Ascend-H323-Dialed-Time',
- 'ascend_h323_fegw_address' => 'Ascend-H323-Fegw-Address',
- 'ascend_h323_gatekeeper' => 'Ascend-H323-Gatekeeper',
- 'ascend_handle_ipx' => 'Ascend-Handle-IPX',
- 'ascend_history_weigh_typ' => 'Ascend-History-Weigh-Type',
- 'ascend_home_agent_ip_add' => 'Ascend-Home-Agent-IP-Addr',
- 'ascend_home_agent_passwo' => 'Ascend-Home-Agent-Password',
- 'ascend_home_agent_udp_po' => 'Ascend-Home-Agent-UDP-Port',
- 'ascend_home_network_name' => 'Ascend-Home-Network-Name',
- 'ascend_host_info' => 'Ascend-Host-Info',
- 'ascend_idle_limit' => 'Ascend-Idle-Limit',
- 'ascend_if_netmask' => 'Ascend-IF-Netmask',
- 'ascend_inc_channel_count' => 'Ascend-Inc-Channel-Count',
- 'ascend_inter_arrival_jit' => 'Ascend-Inter-Arrival-Jitter',
- 'ascend_ip_direct' => 'Ascend-IP-Direct',
- 'ascend_ip_pool_chaining' => 'Ascend-IP-Pool-Chaining',
- 'ascend_ip_pool_definitio' => 'Ascend-IP-Pool-Definition',
- 'ascend_ip_tos' => 'Ascend-IP-TOS',
- 'ascend_ip_tos_apply_to' => 'Ascend-IP-TOS-Apply-To',
- 'ascend_ip_tos_precedence' => 'Ascend-IP-TOS-Precedence',
- 'ascend_ipsec_profile' => 'Ascend-IPSEC-Profile',
- 'ascend_ipx_alias' => 'Ascend-IPX-Alias',
- 'ascend_ipx_header_compre' => 'Ascend-IPX-Header-Compression',
- 'ascend_ipx_node_addr' => 'Ascend-IPX-Node-Addr',
- 'ascend_ipx_peer_mode' => 'Ascend-IPX-Peer-Mode',
- 'ascend_ipx_route' => 'Ascend-IPX-Route',
- 'ascend_link_compression' => 'Ascend-Link-Compression',
- 'ascend_max_shared_users' => 'Ascend-Max-Shared-Users',
- 'ascend_maximum_call_dura' => 'Ascend-Maximum-Call-Duration',
- 'ascend_maximum_channels' => 'Ascend-Maximum-Channels',
- 'ascend_maximum_time' => 'Ascend-Maximum-Time',
- 'ascend_menu_item' => 'Ascend-Menu-Item',
- 'ascend_menu_selector' => 'Ascend-Menu-Selector',
- 'ascend_metric' => 'Ascend-Metric',
- 'ascend_minimum_channels' => 'Ascend-Minimum-Channels',
- 'ascend_modem_portno' => 'Ascend-Modem-PortNo',
- 'ascend_modem_shelfno' => 'Ascend-Modem-ShelfNo',
- 'ascend_modem_slotno' => 'Ascend-Modem-SlotNo',
- 'ascend_mpp_idle_percent' => 'Ascend-MPP-Idle-Percent',
- 'ascend_mtu' => 'Ascend-MTU',
- 'ascend_multicast_client' => 'Ascend-Multicast-Client',
- 'ascend_multicast_gleave_' => 'Ascend-Multicast-GLeave-Delay',
- 'ascend_multicast_rate_li' => 'Ascend-Multicast-Rate-Limit',
- 'ascend_multilink_id' => 'Ascend-Multilink-ID',
- 'ascend_nas_port_format' => 'Ascend-NAS-Port-Format',
- 'ascend_netware_timeout' => 'Ascend-Netware-timeout',
- 'ascend_num_in_multilink' => 'Ascend-Num-In-Multilink',
- 'ascend_number_sessions' => 'Ascend-Number-Sessions',
- 'ascend_numbering_plan_id' => 'Ascend-Numbering-Plan-ID',
- 'ascend_owner_ip_addr' => 'Ascend-Owner-IP-Addr',
- 'ascend_port_redir_portnu' => 'Ascend-Port-Redir-Portnum',
- 'ascend_port_redir_protoc' => 'Ascend-Port-Redir-Protocol',
- 'ascend_port_redir_server' => 'Ascend-Port-Redir-Server',
- 'ascend_ppp_address' => 'Ascend-PPP-Address',
- 'ascend_ppp_async_map' => 'Ascend-PPP-Async-Map',
- 'ascend_ppp_vj_1172' => 'Ascend-PPP-VJ-1172',
- 'ascend_ppp_vj_slot_comp' => 'Ascend-PPP-VJ-Slot-Comp',
- 'ascend_pppoe_enable' => 'Ascend-PPPoE-Enable',
- 'ascend_pre_input_octets' => 'Ascend-Pre-Input-Octets',
- 'ascend_pre_input_packets' => 'Ascend-Pre-Input-Packets',
+ 'x_ascend_bridge' => 'X-Ascend-Bridge',
+ '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_pre_output_packet' => 'Ascend-Pre-Output-Packets',
- 'ascend_preempt_limit' => 'Ascend-Preempt-Limit',
- 'ascend_presession_time' => 'Ascend-PreSession-Time',
- 'ascend_pri_number_type' => 'Ascend-PRI-Number-Type',
+ 'ascend_calling_id_number' => 'Ascend-Calling-Id-Number-Plan',
+ 'framed_appletalk_zone' => 'Framed-AppleTalk-Zone',
+ 'annex_audit_level' => 'Annex-Audit-Level',
+ 'digest_algorithm' => 'Digest-Algorithm',
+ 'bind_auth_context' => 'Bind-Auth-Context',
+ 'ascend_user_acct_base' => 'Ascend-User-Acct-Base',
+ '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',
+ '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',
+ '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',
- 'ascend_private_route' => 'Ascend-Private-Route',
- 'ascend_private_route_req' => 'Ascend-Private-Route-Required',
- 'ascend_private_route_tab' => 'Ascend-Private-Route-Table-ID',
- 'ascend_pw_lifetime' => 'Ascend-PW-Lifetime',
- 'ascend_pw_warntime' => 'Ascend-PW-Warntime',
- 'ascend_qos_downstream' => 'Ascend-QOS-Downstream',
- 'ascend_qos_upstream' => 'Ascend-QOS-Upstream',
- 'ascend_receive_secret' => 'Ascend-Receive-Secret',
- 'ascend_recv_name' => 'Ascend-Recv-Name',
- 'ascend_redirect_number' => 'Ascend-Redirect-Number',
- 'ascend_remote_addr' => 'Ascend-Remote-Addr',
- 'ascend_remote_fw' => 'Ascend-Remote-FW',
- 'ascend_remove_seconds' => 'Ascend-Remove-Seconds',
- 'ascend_require_auth' => 'Ascend-Require-Auth',
- 'ascend_route_appletalk' => 'Ascend-Route-Appletalk',
- 'ascend_route_ip' => 'Ascend-Route-IP',
- 'ascend_route_ipx' => 'Ascend-Route-IPX',
+ 'acct_session_time' => 'Acct-Session-Time',
+ 'framed_ip_address' => 'Framed-IP-Address',
+ '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',
+ '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_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',
- 'ascend_seconds_of_histor' => 'Ascend-Seconds-Of-History',
- 'ascend_send_auth' => 'Ascend-Send-Auth',
- 'ascend_send_passwd' => 'Ascend-Send-Passwd',
- 'ascend_send_secret' => 'Ascend-Send-Secret',
- 'ascend_service_type' => 'Ascend-Service-Type',
- 'ascend_session_svr_key' => 'Ascend-Session-Svr-Key',
- 'ascend_session_type' => 'Ascend-Session-Type',
- 'ascend_shared_profile_en' => 'Ascend-Shared-Profile-Enable',
- 'ascend_source_auth' => 'Ascend-Source-Auth',
- 'ascend_source_ip_check' => 'Ascend-Source-IP-Check',
- 'ascend_svc_enabled' => 'Ascend-SVC-Enabled',
- 'ascend_target_util' => 'Ascend-Target-Util',
- 'ascend_telnet_profile' => 'Ascend-Telnet-Profile',
- 'ascend_temporary_rtes' => 'Ascend-Temporary-Rtes',
- 'ascend_third_prompt' => 'Ascend-Third-Prompt',
- 'ascend_token_expiry' => 'Ascend-Token-Expiry',
- 'ascend_token_idle' => 'Ascend-Token-Idle',
- 'ascend_token_immediate' => 'Ascend-Token-Immediate',
- 'ascend_traffic_shaper' => 'Ascend-Traffic-Shaper',
- 'ascend_transit_number' => 'Ascend-Transit-Number',
- 'ascend_ts_idle_limit' => 'Ascend-TS-Idle-Limit',
- 'ascend_ts_idle_mode' => 'Ascend-TS-Idle-Mode',
- 'ascend_tunnel_vrouter_na' => 'Ascend-Tunnel-VRouter-Name',
- 'ascend_tunneling_protoco' => 'Ascend-Tunneling-Protocol',
- 'ascend_user_acct_base' => 'Ascend-User-Acct-Base',
- 'ascend_user_acct_host' => 'Ascend-User-Acct-Host',
- 'ascend_user_acct_key' => 'Ascend-User-Acct-Key',
- 'ascend_user_acct_port' => 'Ascend-User-Acct-Port',
- 'ascend_user_acct_time' => 'Ascend-User-Acct-Time',
- 'ascend_user_acct_type' => 'Ascend-User-Acct-Type',
- 'ascend_uu_info' => 'Ascend-UU-Info',
- 'ascend_vrouter_name' => 'Ascend-VRouter-Name',
- 'ascend_x25_cug' => 'Ascend-X25-Cug',
- 'ascend_x25_nui' => 'Ascend-X25-Nui',
- 'ascend_x25_nui_password_' => 'Ascend-X25-Nui-Password-Prompt',
- 'ascend_x25_nui_prompt' => 'Ascend-X25-Nui-Prompt',
- 'ascend_x25_pad_alias_1' => 'Ascend-X25-Pad-Alias-1',
- 'ascend_x25_pad_alias_2' => 'Ascend-X25-Pad-Alias-2',
- 'ascend_x25_pad_alias_3' => 'Ascend-X25-Pad-Alias-3',
- 'ascend_x25_pad_banner' => 'Ascend-X25-Pad-Banner',
- 'ascend_x25_pad_prompt' => 'Ascend-X25-Pad-Prompt',
- 'ascend_x25_pad_x3_parame' => 'Ascend-X25-Pad-X3-Parameters',
- 'ascend_x25_pad_x3_profil' => 'Ascend-X25-Pad-X3-Profile',
- 'ascend_x25_profile_name' => 'Ascend-X25-Profile-Name',
- 'ascend_x25_reverse_charg' => 'Ascend-X25-Reverse-Charging',
- 'ascend_x25_rpoa' => 'Ascend-X25-Rpoa',
- 'ascend_x25_x121_address' => 'Ascend-X25-X121-Address',
- 'ascend_xmit_rate' => 'Ascend-Xmit-Rate',
- 'assigned_ip_address' => 'Assigned_IP_Address',
- 'assigned_ip_addrest' => 'Assigned-IP-Address',
- 'auth_type' => 'Auth-Type',
- 'autz_type' => 'Autz-Type',
- 'bg_aging_time' => 'BG_Aging_Time',
- 'bg_aging_timf' => 'BG-Aging-Time',
- 'bg_path_cost' => 'BG_Path_Cost',
- 'bg_path_cosu' => 'BG-Path-Cost',
- 'bg_span_dis' => 'BG_Span_Dis',
- 'bg_span_dit' => 'BG-Span-Dis',
- 'bg_trans_bpdu' => 'BG_Trans_BPDU',
- 'bg_trans_bpdv' => 'BG-Trans-BPDU',
- 'bind_auth_context' => 'Bind_Auth_Context',
- 'bind_auth_contexu' => 'Bind-Auth-Context',
- 'bind_auth_max_sessions' => 'Bind_Auth_Max_Sessions',
- 'bind_auth_max_sessiont' => 'Bind-Auth-Max-Sessions',
- 'bind_auth_protocol' => 'Bind_Auth_Protocol',
- 'bind_auth_protocom' => 'Bind-Auth-Protocol',
- 'bind_auth_service_grp' => 'Bind_Auth_Service_Grp',
- 'bind_auth_service_grq' => 'Bind-Auth-Service-Grp',
- 'bind_bypass_bypass' => 'Bind_Bypass_Bypass',
- 'bind_bypass_bypast' => 'Bind-Bypass-Bypass',
- 'bind_bypass_context' => 'Bind_Bypass_Context',
- 'bind_bypass_contexu' => 'Bind-Bypass-Context',
- 'bind_dot1q_port' => 'Bind_Dot1q_Port',
- 'bind_dot1q_poru' => 'Bind-Dot1q-Port',
- 'bind_dot1q_slot' => 'Bind_Dot1q_Slot',
- 'bind_dot1q_slou' => 'Bind-Dot1q-Slot',
- 'bind_dot1q_vlan_tag_id' => 'Bind_Dot1q_Vlan_Tag_Id',
- 'bind_dot1q_vlan_tag_ie' => 'Bind-Dot1q-Vlan-Tag-Id',
- 'bind_int_context' => 'Bind_Int_Context',
- 'bind_int_contexu' => 'Bind-Int-Context',
- 'bind_int_interface_name' => 'Bind_Int_Interface_Name',
- 'bind_int_interface_namf' => 'Bind-Int-Interface-Name',
- 'bind_l2tp_flow_control' => 'Bind_L2TP_Flow_Control',
- 'bind_l2tp_flow_controm' => 'Bind-L2TP-Flow-Control',
- 'bind_l2tp_tunnel_name' => 'Bind_L2TP_Tunnel_Name',
- 'bind_l2tp_tunnel_namf' => 'Bind-L2TP-Tunnel-Name',
- 'bind_ses_context' => 'Bind_Ses_Context',
- 'bind_ses_contexu' => 'Bind-Ses-Context',
- 'bind_sub_password' => 'Bind_Sub_Password',
- 'bind_sub_passwore' => 'Bind-Sub-Password',
- 'bind_sub_user_at_context' => 'Bind_Sub_User_At_Context',
- 'bind_sub_user_at_contexu' => 'Bind-Sub-User-At-Context',
- 'bind_tun_context' => 'Bind_Tun_Context',
- 'bind_tun_contexu' => 'Bind-Tun-Context',
- 'bind_type' => 'Bind_Type',
- 'bind_typf' => 'Bind-Type',
- 'bintec_bibodialtable' => 'BinTec-biboDialTable',
- 'bintec_biboppptable' => 'BinTec-biboPPPTable',
- 'bintec_ipextiftable' => 'BinTec-ipExtIfTable',
- 'bintec_ipextrttable' => 'BinTec-ipExtRtTable',
- 'bintec_ipfiltertable' => 'BinTec-ipFilterTable',
- 'bintec_ipnatpresettable' => 'BinTec-ipNatPresetTable',
- 'bintec_ipqostable' => 'BinTec-ipQoSTable',
- 'bintec_iproutetable' => 'BinTec-ipRouteTable',
- 'bintec_ipxcirctable' => 'BinTec-ipxCircTable',
- 'bintec_ipxstaticroutetab' => 'BinTec-ipxStaticRouteTable',
- 'bintec_ipxstaticservtabl' => 'BinTec-ipxStaticServTable',
- 'bintec_ospfiftable' => 'BinTec-ospfIfTable',
- 'bintec_pppextiftable' => 'BinTec-pppExtIfTable',
- 'bintec_qosiftable' => 'BinTec-qosIfTable',
- 'bintec_qospolicytable' => 'BinTec-qosPolicyTable',
- 'bintec_ripcirctable' => 'BinTec-ripCircTable',
- 'bintec_sapcirctable' => 'BinTec-sapCircTable',
- 'bridge_group' => 'Bridge_Group',
- 'bridge_grouq' => 'Bridge-Group',
- 'cabletron_protocol_calla' => 'Cabletron-Protocol-Callable',
- 'cabletron_protocol_enabl' => 'Cabletron-Protocol-Enable',
- 'call_id' => 'call-id',
- 'callback_id' => 'Callback-Id',
- 'callback_number' => 'Callback-Number',
- 'called_station_id' => 'Called-Station-Id',
- 'caller_id' => 'Caller-ID',
- 'calling_station_id' => 'Calling-Station-Id',
- 'cbbsm_bandwidth' => 'CBBSM-Bandwidth',
- 'challenge_state' => 'Challenge-State',
- 'chap_challenge' => 'CHAP-Challenge',
- 'chap_password' => 'CHAP-Password',
- 'char_noecho' => 'Char-Noecho',
- 'cisco_abort_cause' => 'Cisco-Abort-Cause',
- 'cisco_account_info' => 'Cisco-Account-Info',
- 'cisco_assign_ip_pool' => 'Cisco-Assign-IP-Pool',
- 'cisco_avpair' => 'Cisco-AVPair',
- 'cisco_call_filter' => 'Cisco-Call-Filter',
- 'cisco_call_type' => 'Cisco-Call-Type',
- 'cisco_command_code' => 'Cisco-Command-Code',
- 'cisco_control_info' => 'Cisco-Control-Info',
- 'cisco_data_filter' => 'Cisco-Data-Filter',
- 'cisco_data_rate' => 'Cisco-Data-Rate',
- 'cisco_disconnect_cause' => 'Cisco-Disconnect-Cause',
- 'cisco_email_server_ack_f' => 'Cisco-Email-Server-Ack-Flag',
- 'cisco_email_server_addre' => 'Cisco-Email-Server-Address',
- 'cisco_fax_account_id_ori' => 'Cisco-Fax-Account-Id-Origin',
- 'cisco_fax_auth_status' => 'Cisco-Fax-Auth-Status',
- 'cisco_fax_connect_speed' => 'Cisco-Fax-Connect-Speed',
- 'cisco_fax_coverpage_flag' => 'Cisco-Fax-Coverpage-Flag',
- 'cisco_fax_dsn_address' => 'Cisco-Fax-Dsn-Address',
- 'cisco_fax_dsn_flag' => 'Cisco-Fax-Dsn-Flag',
- 'cisco_fax_mdn_address' => 'Cisco-Fax-Mdn-Address',
- 'cisco_fax_mdn_flag' => 'Cisco-Fax-Mdn-Flag',
- 'cisco_fax_modem_time' => 'Cisco-Fax-Modem-Time',
- 'cisco_fax_msg_id' => 'Cisco-Fax-Msg-Id',
- 'cisco_fax_pages' => 'Cisco-Fax-Pages',
- 'cisco_fax_process_abort_' => 'Cisco-Fax-Process-Abort-Flag',
- 'cisco_fax_recipient_coun' => 'Cisco-Fax-Recipient-Count',
- 'cisco_gateway_id' => 'Cisco-Gateway-Id',
- 'cisco_idle_limit' => 'Cisco-Idle-Limit',
- 'cisco_ip_direct' => 'Cisco-IP-Direct',
- 'cisco_ip_pool_definition' => 'Cisco-IP-Pool-Definition',
- 'cisco_link_compression' => 'Cisco-Link-Compression',
- 'cisco_maximum_channels' => 'Cisco-Maximum-Channels',
- 'cisco_maximum_time' => 'Cisco-Maximum-Time',
- 'cisco_multilink_id' => 'Cisco-Multilink-ID',
- 'cisco_nas_port' => 'Cisco-NAS-Port',
- 'cisco_num_in_multilink' => 'Cisco-Num-In-Multilink',
- 'cisco_port_used' => 'Cisco-Port-Used',
- 'cisco_ppp_async_map' => 'Cisco-PPP-Async-Map',
- 'cisco_ppp_vj_slot_comp' => 'Cisco-PPP-VJ-Slot-Comp',
- 'cisco_pre_input_octets' => 'Cisco-Pre-Input-Octets',
- 'cisco_pre_input_packets' => 'Cisco-Pre-Input-Packets',
- 'cisco_pre_output_octets' => 'Cisco-Pre-Output-Octets',
- 'cisco_pre_output_packets' => 'Cisco-Pre-Output-Packets',
- 'cisco_presession_time' => 'Cisco-PreSession-Time',
- 'cisco_pw_lifetime' => 'Cisco-PW-Lifetime',
- 'cisco_route_ip' => 'Cisco-Route-IP',
- 'cisco_service_info' => 'Cisco-Service-Info',
- 'cisco_target_util' => 'Cisco-Target-Util',
- 'cisco_xmit_rate' => 'Cisco-Xmit-Rate',
- 'class' => 'Class',
- 'client_dns_pri' => 'Client_DNS_Pri',
- 'client_dns_prj' => 'Client-DNS-Pri',
- 'client_dns_sec' => 'Client_DNS_Sec',
- 'client_dns_sed' => 'Client-DNS-Sec',
- 'client_id' => 'Client-Id',
- 'client_ip_address' => 'Client-IP-Address',
- 'client_port_dnis' => 'Client-Port-DNIS',
- 'client_port_id' => 'Client-Port-Id',
- 'colubris_avpair' => 'Colubris-AVPair',
- 'configuration_token' => 'Configuration-Token',
- 'connect_info' => 'Connect-Info',
- 'connect_rate' => 'Connect-Rate',
- 'context_name' => 'Context_Name',
- 'context_namf' => 'Context-Name',
- 'crypt_password' => 'Crypt-Password',
- 'current_time' => 'Current-Time',
- 'cvpn3000_access_hours' => 'CVPN3000-Access-Hours',
- 'cvpn3000_allow_network_e' => 'CVPN3000-Allow-Network-Extension-Mode',
- 'cvpn3000_auth_server_pas' => 'CVPN3000-Auth-Server-Password',
- 'cvpn3000_auth_server_pri' => 'CVPN3000-Auth-Server-Priority',
- 'cvpn3000_auth_server_typ' => 'CVPN3000-Auth-Server-Type',
- 'cvpn3000_authd_user_idle' => 'CVPN3000-Authd-User-Idle-Timeout',
- 'cvpn3000_cisco_ip_phone_' => 'CVPN3000-Cisco-IP-Phone-Bypass',
- 'cvpn3000_dhcp_network_sc' => 'CVPN3000-DHCP-Network-Scope',
- 'cvpn3000_ike_keep_alives' => 'CVPN3000-IKE-Keep-Alives',
+ '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',
+ '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',
+ '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',
+ 'cvx_identification' => 'CVX-Identification',
'cvpn3000_ipsec_allow_pas' => 'CVPN3000-IPSec-Allow-Passwd-Store',
- 'cvpn3000_ipsec_auth_on_r' => 'CVPN3000-IPSec-Auth-On-Rekey',
- 'cvpn3000_ipsec_authentic' => 'CVPN3000-IPSec-Authentication',
- 'cvpn3000_ipsec_authoriza' => 'CVPN3000-IPSec-Authorization-Type',
- 'cvpn3000_ipsec_authorizb' => 'CVPN3000-IPSec-Authorization-Required',
- 'cvpn3000_ipsec_backup_se' => 'CVPN3000-IPSec-Backup-Servers',
- 'cvpn3000_ipsec_backup_sf' => 'CVPN3000-IPSec-Backup-Server-List',
- 'cvpn3000_ipsec_banner1' => 'CVPN3000-IPSec-Banner1',
- 'cvpn3000_ipsec_banner2' => 'CVPN3000-IPSec-Banner2',
- 'cvpn3000_ipsec_client_fw' => 'CVPN3000-IPSec-Client-Fw-Filter-Name',
- 'cvpn3000_ipsec_client_fx' => 'CVPN3000-IPSec-Client-Fw-Filter-Opt',
- 'cvpn3000_ipsec_confidenc' => 'CVPN3000-IPSec-Confidence-Level',
- 'cvpn3000_ipsec_default_d' => 'CVPN3000-IPSec-Default-Domain',
- 'cvpn3000_ipsec_dn_field' => 'CVPN3000-IPSec-DN-Field',
- 'cvpn3000_ipsec_group_nam' => 'CVPN3000-IPSec-Group-Name',
- 'cvpn3000_ipsec_ike_peer_' => 'CVPN3000-IPSec-IKE-Peer-ID-Check',
- 'cvpn3000_ipsec_ip_compre' => 'CVPN3000-IPSec-IP-Compression',
- 'cvpn3000_ipsec_ltl_keepa' => 'CVPN3000-IPSec-LTL-Keepalives',
- 'cvpn3000_ipsec_mode_conf' => 'CVPN3000-IPSec-Mode-Config',
- 'cvpn3000_ipsec_over_udp' => 'CVPN3000-IPSec-Over-UDP',
- 'cvpn3000_ipsec_over_udp_' => 'CVPN3000-IPSec-Over-UDP-Port',
+ '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',
+ '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',
- 'cvpn3000_ipsec_sec_assoc' => 'CVPN3000-IPSec-Sec-Association',
- 'cvpn3000_ipsec_split_dns' => 'CVPN3000-IPSec-Split-DNS-Names',
- 'cvpn3000_ipsec_split_tun' => 'CVPN3000-IPSec-Split-Tunnel-List',
- 'cvpn3000_ipsec_split_tuo' => 'CVPN3000-IPSec-Split-Tunneling-Policy',
- 'cvpn3000_ipsec_tunnel_ty' => 'CVPN3000-IPSec-Tunnel-Type',
- 'cvpn3000_ipsec_user_grou' => 'CVPN3000-IPSec-User-Group-Lock',
+ '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',
- 'cvpn3000_l2tp_min_auth_p' => 'CVPN3000-L2TP-Min-Auth-Protocol',
- 'cvpn3000_l2tp_mppc_compr' => 'CVPN3000-L2TP-MPPC-Compression',
- 'cvpn3000_leap_bypass' => 'CVPN3000-LEAP-Bypass',
- 'cvpn3000_ms_client_icpt_' => 'CVPN3000-MS-Client-Icpt-DHCP-Conf-Msg',
- 'cvpn3000_ms_client_subne' => 'CVPN3000-MS-Client-Subnet-Mask',
- 'cvpn3000_partition_max_s' => 'CVPN3000-Partition-Max-Sessions',
- 'cvpn3000_partition_mobil' => 'CVPN3000-Partition-Mobile-IP-Key',
- 'cvpn3000_partition_mobim' => 'CVPN3000-Partition-Mobile-IP-Address',
- 'cvpn3000_partition_mobin' => 'CVPN3000-Partition-Mobile-IP-SPI',
- 'cvpn3000_partition_premi' => 'CVPN3000-Partition-Premise-Router',
- 'cvpn3000_partition_prima' => 'CVPN3000-Partition-Primary-DHCP',
- 'cvpn3000_partition_secon' => 'CVPN3000-Partition-Secondary-DHCP',
- 'cvpn3000_pptp_encryption' => 'CVPN3000-PPTP-Encryption',
- 'cvpn3000_pptp_min_auth_p' => 'CVPN3000-PPTP-Min-Auth-Protocol',
- 'cvpn3000_pptp_mppc_compr' => 'CVPN3000-PPTP-MPPC-Compression',
- 'cvpn3000_primary_dns' => 'CVPN3000-Primary-DNS',
- 'cvpn3000_primary_wins' => 'CVPN3000-Primary-WINS',
- 'cvpn3000_priority_on_sep' => 'CVPN3000-Priority-On-SEP',
- 'cvpn3000_reqrd_client_fw' => 'CVPN3000-Reqrd-Client-Fw-Vendor-Code',
- 'cvpn3000_reqrd_client_fx' => 'CVPN3000-Reqrd-Client-Fw-Product-Code',
+ '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',
- 'cvpn3000_request_auth_ve' => 'CVPN3000-Request-Auth-Vector',
- 'cvpn3000_require_hw_clie' => 'CVPN3000-Require-HW-Client-Auth',
- 'cvpn3000_require_individ' => 'CVPN3000-Require-Individual-User-Auth',
- 'cvpn3000_secondary_dns' => 'CVPN3000-Secondary-DNS',
- 'cvpn3000_secondary_wins' => 'CVPN3000-Secondary-WINS',
- 'cvpn3000_sep_card_assign' => 'CVPN3000-SEP-Card-Assignment',
- 'cvpn3000_simultaneous_lo' => 'CVPN3000-Simultaneous-Logins',
- 'cvpn3000_strip_realm' => 'CVPN3000-Strip-Realm',
- 'cvpn3000_tunneling_proto' => 'CVPN3000-Tunneling-Protocols',
- 'cvpn3000_use_client_addr' => 'CVPN3000-Use-Client-Address',
- 'cvpn3000_user_auth_serve' => 'CVPN3000-User-Auth-Server-Name',
- 'cvpn3000_user_auth_servf' => 'CVPN3000-User-Auth-Server-Port',
- 'cvpn3000_user_auth_servg' => 'CVPN3000-User-Auth-Server-Secret',
- 'cvpn5000_client_assigned' => 'CVPN5000-Client-Assigned-IP',
- 'cvpn5000_client_assignee' => 'CVPN5000-Client-Assigned-IPX',
- 'cvpn5000_client_real_ip' => 'CVPN5000-Client-Real-IP',
- 'cvpn5000_echo' => 'CVPN5000-Echo',
- 'cvpn5000_tunnel_throughp' => 'CVPN5000-Tunnel-Throughput',
- 'cvpn5000_vpn_groupinfo' => 'CVPN5000-VPN-GroupInfo',
- 'cvpn5000_vpn_password' => 'CVPN5000-VPN-Password',
- 'cvx_assign_ip_pool' => 'CVX-Assign-IP-Pool',
- 'cvx_client_assign_dns' => 'CVX-Client-Assign-DNS',
- 'cvx_data_filter' => 'CVX-Data-Filter',
- 'cvx_data_rate' => 'CVX-Data-Rate',
- 'cvx_disconnect_cause' => 'CVX-Disconnect-Cause',
- 'cvx_identification' => 'CVX-Identification',
- 'cvx_idle_limit' => 'CVX-Idle-Limit',
- 'cvx_ipsvc_aznlvl' => 'CVX-IPSVC-AZNLVL',
- 'cvx_ipsvc_mask' => 'CVX-IPSVC-Mask',
- 'cvx_maximum_channels' => 'CVX-Maximum-Channels',
- 'cvx_modem_begin_modulati' => 'CVX-Modem-Begin-Modulation',
- 'cvx_modem_begin_recv_lin' => 'CVX-Modem-Begin-Recv-Line-Lvl',
- 'cvx_modem_data_compressi' => 'CVX-Modem-Data-Compression',
+ '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_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_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_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',
+ '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_fr_n391' => 'Ascend-FR-N391',
+ 'ascend_remote_addr' => 'Ascend-Remote-Addr',
+ 'client_port_id' => 'Client-Port-Id',
+ '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',
'cvx_modem_end_modulation' => 'CVX-Modem-End-Modulation',
- 'cvx_modem_end_recv_line_' => 'CVX-Modem-End-Recv-Line-Lvl',
- 'cvx_modem_error_correcti' => 'CVX-Modem-Error-Correction',
- 'cvx_modem_local_rate_neg' => 'CVX-Modem-Local-Rate-Negs',
- 'cvx_modem_local_retrains' => 'CVX-Modem-Local-Retrains',
- 'cvx_modem_remote_rate_ne' => 'CVX-Modem-Remote-Rate-Negs',
- 'cvx_modem_remote_retrain' => 'CVX-Modem-Remote-Retrains',
- 'cvx_modem_retx_packets' => 'CVX-Modem-ReTx-Packets',
- 'cvx_modem_snr' => 'CVX-Modem-SNR',
- 'cvx_modem_tx_packets' => 'CVX-Modem-Tx-Packets',
- 'cvx_multicast_client' => 'CVX-Multicast-Client',
- 'cvx_multicast_rate_limit' => 'CVX-Multicast-Rate-Limit',
- 'cvx_multilink_group_numb' => 'CVX-Multilink-Group-Number',
- 'cvx_multilink_match_info' => 'CVX-Multilink-Match-Info',
- 'cvx_ppp_address' => 'CVX-PPP-Address',
- 'cvx_ppp_log_mask' => 'CVX-PPP-Log-Mask',
- 'cvx_presession_time' => 'CVX-PreSession-Time',
- 'cvx_primary_dns' => 'CVX-Primary-DNS',
- 'cvx_radius_redirect' => 'CVX-Radius-Redirect',
- 'cvx_secondary_dns' => 'CVX-Secondary-DNS',
- 'cvx_ss7_session_id_type' => 'CVX-SS7-Session-ID-Type',
- 'cvx_vpop_id' => 'CVX-VPOP-ID',
- 'cvx_xmit_rate' => 'CVX-Xmit-Rate',
- 'dhcp_max_leases' => 'DHCP_Max_Leases',
- 'dhcp_max_leaset' => 'DHCP-Max-Leases',
- 'dialback_name' => 'Dialback-Name',
- 'dialback_no' => 'Dialback-No',
- 'digest_algorithm' => 'Digest-Algorithm',
- 'digest_attributes' => 'Digest-Attributes',
- 'digest_body_digest' => 'Digest-Body-Digest',
- 'digest_cnonce' => 'Digest-CNonce',
- 'digest_method' => 'Digest-Method',
- 'digest_nonce' => 'Digest-Nonce',
- 'digest_nonce_count' => 'Digest-Nonce-Count',
- 'digest_qop' => 'Digest-QOP',
- 'digest_realm' => 'Digest-Realm',
- 'digest_response' => 'Digest-Response',
- 'digest_uri' => 'Digest-URI',
- 'digest_user_name' => 'Digest-User-Name',
- 'eap_code' => 'EAP-Code',
- 'eap_id' => 'EAP-Id',
- 'eap_md5_password' => 'EAP-MD5-Password',
- 'eap_message' => 'EAP-Message',
- 'eap_sim_any_id_req' => 'EAP-Sim-ANY_ID_REQ',
- 'eap_sim_checkcode' => 'EAP-Sim-CHECKCODE',
- 'eap_sim_counter' => 'EAP-Sim-COUNTER',
- 'eap_sim_counter_too_smal' => 'EAP-Sim-COUNTER_TOO_SMALL',
- 'eap_sim_encr_data' => 'EAP-Sim-ENCR_DATA',
- 'eap_sim_extra' => 'EAP-Sim-EXTRA',
- 'eap_sim_fullauth_id_req' => 'EAP-Sim-FULLAUTH_ID_REQ',
- 'eap_sim_hmac' => 'EAP-Sim-HMAC',
- 'eap_sim_identity' => 'EAP-Sim-IDENTITY',
- 'eap_sim_imsi' => 'EAP-Sim-IMSI',
- 'eap_sim_iv' => 'EAP-Sim-IV',
- 'eap_sim_kc1' => 'EAP-Sim-KC1',
- 'eap_sim_kc2' => 'EAP-Sim-KC2',
- 'eap_sim_kc3' => 'EAP-Sim-KC3',
- 'eap_sim_key' => 'EAP-Sim-KEY',
- 'eap_sim_mac' => 'EAP-Sim-MAC',
- 'eap_sim_next_pseudonum' => 'EAP-Sim-NEXT_PSEUDONUM',
- 'eap_sim_next_reauth_id' => 'EAP-Sim-NEXT_REAUTH_ID',
- 'eap_sim_nonce_mt' => 'EAP-Sim-NONCE_MT',
- 'eap_sim_nonce_s' => 'EAP-Sim-NONCE_S',
- 'eap_sim_notification' => 'EAP-Sim-NOTIFICATION',
- 'eap_sim_padding' => 'EAP-Sim-PADDING',
- 'eap_sim_permanent_id_req' => 'EAP-Sim-PERMANENT_ID_REQ',
- 'eap_sim_rand' => 'EAP-Sim-RAND',
- 'eap_sim_rand1' => 'EAP-Sim-Rand1',
- 'eap_sim_rand2' => 'EAP-Sim-Rand2',
- 'eap_sim_rand3' => 'EAP-Sim-Rand3',
- 'eap_sim_selected_version' => 'EAP-Sim-SELECTED_VERSION',
- 'eap_sim_sres1' => 'EAP-Sim-SRES1',
- 'eap_sim_sres2' => 'EAP-Sim-SRES2',
- 'eap_sim_sres3' => 'EAP-Sim-SRES3',
- 'eap_sim_state' => 'EAP-Sim-State',
- 'eap_sim_subtype' => 'EAP-Sim-Subtype',
- 'eap_sim_version_list' => 'EAP-Sim-VERSION_LIST',
- 'eap_tls_require_client_c' => 'EAP-TLS-Require-Client-Cert',
- 'eap_type' => 'EAP-Type',
- 'eap_type_gtc' => 'EAP-Type-GTC',
- 'eap_type_identity' => 'EAP-Type-Identity',
- 'eap_type_leap' => 'EAP-Type-LEAP',
- 'eap_type_md5' => 'EAP-Type-MD5',
- 'eap_type_nak' => 'EAP-Type-NAK',
- 'eap_type_notification' => 'EAP-Type-Notification',
- 'eap_type_otp' => 'EAP-Type-OTP',
- 'eap_type_peap' => 'EAP-Type-PEAP',
- 'eap_type_sim' => 'EAP-Type-SIM',
- 'eap_type_sim2' => 'EAP-Type-SIM2',
- 'eap_type_tls' => 'EAP-Type-TLS',
- 'eap_type_ttls' => 'EAP-Type-TTLS',
- 'error_cause' => 'Error-Cause',
- 'erx_address_pool_name' => 'ERX-Address-Pool-Name',
- 'erx_alternate_cli_access' => 'ERX-Alternate-Cli-Access-Level',
- 'erx_alternate_cli_vroute' => 'ERX-Alternate-Cli-Vrouter-Name',
- 'erx_atm_mbs' => 'ERX-Atm-MBS',
- 'erx_atm_pcr' => 'ERX-Atm-PCR',
- 'erx_atm_scr' => 'ERX-Atm-SCR',
- 'erx_atm_service_category' => 'ERX-Atm-Service-Category',
- 'erx_bearer_type' => 'ERX-Bearer-Type',
- 'erx_cli_allow_all_vr_acc' => 'ERX-Cli-Allow-All-VR-Access',
- 'erx_cli_initial_access_l' => 'ERX-Cli-Initial-Access-Level',
- 'erx_dial_out_number' => 'ERX-Dial-Out-Number',
- 'erx_egress_policy_name' => 'ERX-Egress-Policy-Name',
- 'erx_egress_statistics' => 'ERX-Egress-Statistics',
- 'erx_framed_ip_route_tag' => 'ERX-Framed-Ip-Route-Tag',
- 'erx_igmp_enable' => 'ERX-Igmp-Enable',
- 'erx_ingress_policy_name' => 'ERX-Ingress-Policy-Name',
- 'erx_ingress_statistics' => 'ERX-Ingress-Statistics',
- 'erx_input_gigapkts' => 'ERX-Input-Gigapkts',
- 'erx_ipv6_local_interface' => 'ERX-IpV6-Local-Interface',
- 'erx_ipv6_primary_dns' => 'ERX-Ipv6-Primary-Dns',
- 'erx_ipv6_secondary_dns' => 'ERX-Ipv6-Secondary-Dns',
- 'erx_ipv6_virtual_router' => 'ERX-IpV6-Virtual-Router',
- 'erx_local_loopback_inter' => 'ERX-Local-Loopback-Interface',
- 'erx_maximum_bps' => 'ERX-Maximum-BPS',
- 'erx_minimum_bps' => 'ERX-Minimum-BPS',
- 'erx_output_gigapkts' => 'ERX-Output-Gigapkts',
- 'erx_ppp_auth_protocol' => 'ERX-PPP-Auth-Protocol',
- 'erx_ppp_password' => 'ERX-PPP-Password',
- 'erx_ppp_username' => 'ERX-PPP-Username',
- 'erx_pppoe_description' => 'ERX-Pppoe-Description',
- 'erx_pppoe_max_sessions' => 'ERX-Pppoe-Max-Sessions',
- 'erx_pppoe_url' => 'ERX-Pppoe-Url',
- 'erx_primary_dns' => 'ERX-Primary-Dns',
- 'erx_primary_wins' => 'ERX-Primary-Wins',
- 'erx_qos_profile_interfac' => 'ERX-Qos-Profile-Interface-Type',
- 'erx_qos_profile_name' => 'ERX-Qos-Profile-Name',
- 'erx_redirect_vr_name' => 'ERX-Redirect-VR-Name',
- 'erx_sa_validate' => 'ERX-Sa-Validate',
- 'erx_secondary_dns' => 'ERX-Secondary-Dns',
- 'erx_secondary_wins' => 'ERX-Secondary-Wins',
- 'erx_service_bundle' => 'ERX-Service-Bundle',
- 'erx_tunnel_interface_id' => 'ERX-Tunnel-Interface-Id',
- 'erx_tunnel_maximum_sessi' => 'ERX-Tunnel-Maximum-Sessions',
+ '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',
+ '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',
+ 'x_ascend_idle_limit' => 'X-Ascend-Idle-Limit',
+ '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',
+ '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',
+ 'itk_banner' => 'ITK-Banner',
+ 'ascend_ft1_caller' => 'Ascend-FT1-Caller',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'cisco_route_ip' => 'Cisco-Route-IP',
+ '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_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',
+ 'ascend_atm_connect_vpi' => 'Ascend-ATM-Connect-Vpi',
+ 'connect_info' => 'Connect-Info',
+ 'usr_port_tap_address' => 'USR-Port-Tap-Address',
+ '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',
+ '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',
+ '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',
- 'erx_tunnel_password' => 'ERX-Tunnel-Password',
- 'erx_tunnel_tos' => 'ERX-Tunnel-Tos',
+ '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_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',
+ 'ascend_transit_number' => 'Ascend-Transit-Number',
+ 'ascend_cache_refresh' => 'Ascend-Cache-Refresh',
+ 'ascend_user_acct_type' => 'Ascend-User-Acct-Type',
+ 'usr_num_fax_pages_proces' => 'USR-Num-Fax-Pages-Processed',
+ 'usr_mic' => 'USR-MIC',
+ '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',
- 'erx_virtual_router_name' => 'ERX-Virtual-Router-Name',
- 'event_timestamp' => 'Event-Timestamp',
- 'exec_program' => 'Exec-Program',
- 'exec_program_wait' => 'Exec-Program-Wait',
- 'expiration' => 'Expiration',
- 'extreme_netlogin_only' => 'Extreme-Netlogin-Only',
- 'extreme_netlogin_url' => 'Extreme-Netlogin-Url',
+ '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',
+ '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',
+ 'usr_simplified_v42bis_us' => 'USR-Simplified-V42bis-Usage',
+ 'h323_setup_time' => 'h323-setup-time',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'shiva_type_of_service' => 'Shiva-Type-Of-Service',
+ '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_reply_script2' => 'USR-Reply-Script2',
+ 'usr_security_login_limit' => 'USR-Security-Login-Limit',
+ 'cisco_link_compression' => 'Cisco-Link-Compression',
+ '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',
+ 'annex_multilink_id' => 'Annex-Multilink-Id',
+ 'mcast_maxgroupt' => 'Mcast_MaxGroups',
+ 'configuration_token' => 'Configuration-Token',
+ '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',
+ 'erx_ingress_policy_name' => 'ERX-Ingress-Policy-Name',
+ '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',
+ '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',
+ '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_call_end_date_time' => 'USR-Call-End-Date-Time',
+ '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',
+ 'acc_bridging_support' => 'Acc-Bridging-Support',
+ 'usr_channel' => 'USR-Channel',
+ 'arap_security_data' => 'ARAP-Security-Data',
+ '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',
+ 'lac_real_port_typf' => 'LAC_Real_Port_Type',
+ 'usr_channel_connected_to' => 'USR-Channel-Connected-To',
+ 'ascend_client_assign_win' => 'Ascend-Client-Assign-WINS',
+ 'redcreek_tunneled_gatewa' => 'RedCreek-Tunneled-Gateway',
+ 'usr_number_of_fallbacks' => 'USR-Number-of-Fallbacks',
+ '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',
+ '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',
- 'extreme_netlogin_vlan' => 'Extreme-Netlogin-Vlan',
- 'fall_through' => 'Fall-Through',
- 'filter_id' => 'Filter-Id',
- 'foundry_command_exceptio' => 'Foundry-Command-Exception-Flag',
- 'foundry_command_string' => 'Foundry-Command-String',
- 'foundry_inm_privilege' => 'Foundry-INM-Privilege',
- 'foundry_privilege_level' => 'Foundry-Privilege-Level',
- 'framed_address' => 'Framed-Address',
- 'framed_appletalk_link' => 'Framed-AppleTalk-Link',
- 'framed_appletalk_network' => 'Framed-AppleTalk-Network',
- 'framed_appletalk_zone' => 'Framed-AppleTalk-Zone',
- 'framed_callback_id' => 'Framed-Callback-Id',
- 'framed_compression' => 'Framed-Compression',
- 'framed_filter_id' => 'Framed-Filter-Id',
- 'framed_interface_id' => 'Framed-Interface-Id',
- 'framed_ip_address' => 'Framed-IP-Address',
- 'framed_ip_netmask' => 'Framed-IP-Netmask',
- 'framed_ipv6_pool' => 'Framed-IPv6-Pool',
- 'framed_ipv6_prefix' => 'Framed-IPv6-Prefix',
- 'framed_ipv6_route' => 'Framed-IPv6-Route',
- 'framed_ipx_network' => 'Framed-IPX-Network',
- 'framed_mtu' => 'Framed-MTU',
- 'framed_netmask' => 'Framed-Netmask',
- 'framed_pool' => 'Framed-Pool',
- 'framed_protocol' => 'Framed-Protocol',
- 'framed_route' => 'Framed-Route',
- 'framed_routing' => 'Framed-Routing',
- 'freeradius_proxied_to' => 'FreeRADIUS-Proxied-To',
- 'gandalf_around_the_corne' => 'Gandalf-Around-The-Corner',
- 'gandalf_authentication_s' => 'Gandalf-Authentication-String',
- 'gandalf_calling_line_id_' => 'Gandalf-Calling-Line-ID-1',
- 'gandalf_calling_line_ida' => 'Gandalf-Calling-Line-ID-2',
- 'gandalf_channel_group_na' => 'Gandalf-Channel-Group-Name-1',
- 'gandalf_channel_group_nb' => 'Gandalf-Channel-Group-Name-2',
- 'gandalf_compression_stat' => 'Gandalf-Compression-Status',
- 'gandalf_dial_prefix_name' => 'Gandalf-Dial-Prefix-Name-1',
- 'gandalf_dial_prefix_namf' => 'Gandalf-Dial-Prefix-Name-2',
- 'gandalf_fwd_broadcast_in' => 'Gandalf-Fwd-Broadcast-In',
- 'gandalf_fwd_broadcast_ou' => 'Gandalf-Fwd-Broadcast-Out',
- 'gandalf_fwd_multicast_in' => 'Gandalf-Fwd-Multicast-In',
- 'gandalf_fwd_multicast_ou' => 'Gandalf-Fwd-Multicast-Out',
- 'gandalf_fwd_unicast_in' => 'Gandalf-Fwd-Unicast-In',
- 'gandalf_fwd_unicast_out' => 'Gandalf-Fwd-Unicast-Out',
- 'gandalf_hunt_group' => 'Gandalf-Hunt-Group',
- 'gandalf_ipx_spoofing_sta' => 'Gandalf-IPX-Spoofing-State',
- 'gandalf_ipx_watchdog_spo' => 'Gandalf-IPX-Watchdog-Spoof',
- 'gandalf_min_outgoing_bea' => 'Gandalf-Min-Outgoing-Bearer',
- 'gandalf_modem_mode' => 'Gandalf-Modem-Mode',
- 'gandalf_modem_required_1' => 'Gandalf-Modem-Required-1',
- 'gandalf_modem_required_2' => 'Gandalf-Modem-Required-2',
- 'gandalf_operational_mode' => 'Gandalf-Operational-Modes',
- 'gandalf_phone_number_1' => 'Gandalf-Phone-Number-1',
- 'gandalf_phone_number_2' => 'Gandalf-Phone-Number-2',
- 'gandalf_ppp_authenticati' => 'Gandalf-PPP-Authentication',
- 'gandalf_ppp_ncp_type' => 'Gandalf-PPP-NCP-Type',
- 'gandalf_remote_lan_name' => 'Gandalf-Remote-LAN-Name',
- 'gandalf_sap_group_name_1' => 'Gandalf-SAP-Group-Name-1',
- 'gandalf_sap_group_name_2' => 'Gandalf-SAP-Group-Name-2',
- 'gandalf_sap_group_name_3' => 'Gandalf-SAP-Group-Name-3',
- 'gandalf_sap_group_name_4' => 'Gandalf-SAP-Group-Name-4',
- 'gandalf_sap_group_name_5' => 'Gandalf-SAP-Group-Name-5',
- 'garderos_location_name' => 'Garderos-Location-Name',
- 'garderos_service_name' => 'Garderos-Service-Name',
- 'group' => 'Group',
- 'group_name' => 'Group-Name',
- 'gw_final_xlated_cdn' => 'gw-final-xlated-cdn',
- 'gw_rxd_cdn' => 'gw-rxd-cdn',
- 'h323_billing_model' => 'h323-billing-model',
- 'h323_call_origin' => 'h323-call-origin',
- 'h323_call_type' => 'h323-call-type',
- 'h323_conf_id' => 'h323-conf-id',
- 'h323_connect_time' => 'h323-connect-time',
- 'h323_credit_amount' => 'h323-credit-amount',
- 'h323_credit_time' => 'h323-credit-time',
- 'h323_currency' => 'h323-currency',
- 'h323_disconnect_cause' => 'h323-disconnect-cause',
- 'h323_disconnect_time' => 'h323-disconnect-time',
- 'h323_gw_id' => 'h323-gw-id',
- 'h323_incoming_conf_id' => 'h323-incoming-conf-id',
- 'h323_preferred_lang' => 'h323-preferred-lang',
- 'h323_prompt_id' => 'h323-prompt-id',
+ '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',
+ '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',
+ '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',
+ 'acc_access_partition' => 'Acc-Access-Partition',
+ 'usr_power_supply_number' => 'USR-Power-Supply-Number',
+ 'x_ascend_multilink_id' => 'X-Ascend-Multilink-ID',
+ 'redcreek_tunneled_domain' => 'RedCreek-Tunneled-DomainName',
+ 'nomadix_bw_down' => 'Nomadix-Bw-Down',
+ 'acc_ipx_compression' => 'Acc-Ipx-Compression',
+ 'quintum_h323_setup_time' => 'Quintum-h323-setup-time',
+ 'cisco_target_util' => 'Cisco-Target-Util',
+ 'acc_ip_gateway_sec' => 'Acc-Ip-Gateway-Sec',
+ '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',
'h323_redirect_ip_address' => 'h323-redirect-ip-address',
- 'h323_redirect_number' => 'h323-redirect-number',
- 'h323_remote_address' => 'h323-remote-address',
- 'h323_return_code' => 'h323-return-code',
- 'h323_setup_time' => 'h323-setup-time',
- 'h323_time_and_day' => 'h323-time-and-day',
- 'h323_voice_quality' => 'h323-voice-quality',
- 'hint' => 'Hint',
- 'huntgroup_name' => 'Huntgroup-Name',
- 'idle_timeout' => 'Idle-Timeout',
- 'incoming_req_uri' => 'incoming-req-uri',
- 'initial_modulation_type' => 'Initial-Modulation-Type',
- 'ip3_ip_option' => 'IP3-IP-Option',
- 'ip3_rdata_rate' => 'IP3-RData-Rate',
- 'ip3_xdata_rate' => 'IP3-XData-Rate',
- 'ip_address_pool_name' => 'Ip_Address_Pool_Name',
- 'ip_address_pool_namf' => 'Ip-Address-Pool-Name',
- 'ip_host_addr' => 'Ip_Host_Addr',
- 'ip_host_adds' => 'Ip-Host-Addr',
- 'ip_tos_field' => 'IP_TOS_Field',
- 'ip_tos_fiele' => 'IP-TOS-Field',
- 'itk_acct_serv_ip' => 'ITK-Acct-Serv-IP',
- 'itk_acct_serv_prot' => 'ITK-Acct-Serv-Prot',
- 'itk_auth_req_type' => 'ITK-Auth-Req-Type',
- 'itk_auth_serv_ip' => 'ITK-Auth-Serv-IP',
- 'itk_auth_serv_prot' => 'ITK-Auth-Serv-Prot',
- 'itk_banner' => 'ITK-Banner',
- 'itk_channel_binding' => 'ITK-Channel-Binding',
- 'itk_ddi' => 'ITK-DDI',
- 'itk_dest_no' => 'ITK-Dest-No',
- 'itk_dialout_type' => 'ITK-Dialout-Type',
- 'itk_filter_rule' => 'ITK-Filter-Rule',
- 'itk_ftp_auth_ip' => 'ITK-Ftp-Auth-IP',
- 'itk_ip_pool' => 'ITK-IP-Pool',
- 'itk_isdn_prot' => 'ITK-ISDN-Prot',
- 'itk_modem_init_string' => 'ITK-Modem-Init-String',
- 'itk_modem_pool_id' => 'ITK-Modem-Pool-Id',
- 'itk_nas_name' => 'ITK-NAS-Name',
- 'itk_password_prompt' => 'ITK-Password-Prompt',
- 'itk_ppp_auth_type' => 'ITK-PPP-Auth-Type',
- 'itk_ppp_client_server_mo' => 'ITK-PPP-Client-Server-Mode',
- 'itk_ppp_compression_prot' => 'ITK-PPP-Compression-Prot',
- 'itk_prompt' => 'ITK-Prompt',
- 'itk_provider_id' => 'ITK-Provider-Id',
- 'itk_start_delay' => 'ITK-Start-Delay',
- 'itk_tunnel_ip' => 'ITK-Tunnel-IP',
- 'itk_tunnel_prot' => 'ITK-Tunnel-Prot',
- 'itk_usergroup' => 'ITK-Usergroup',
- 'itk_username' => 'ITK-Username',
- 'itk_username_prompt' => 'ITK-Username-Prompt',
- 'itk_users_default_entry' => 'ITK-Users-Default-Entry',
- 'itk_users_default_pw' => 'ITK-Users-Default-Pw',
- 'itk_welcome_message' => 'ITK-Welcome-Message',
- 'juniper_allow_commands' => 'Juniper-Allow-Commands',
- 'juniper_allow_configurat' => 'Juniper-Allow-Configuration',
- 'juniper_deny_commands' => 'Juniper-Deny-Commands',
- 'juniper_deny_configurati' => 'Juniper-Deny-Configuration',
- 'juniper_local_user_name' => 'Juniper-Local-User-Name',
- 'karlnet_turbocell_name' => 'KarlNet-TurboCell-Name',
- 'karlnet_turbocell_opmode' => 'KarlNet-TurboCell-OpMode',
- 'karlnet_turbocell_opstat' => 'KarlNet-TurboCell-OpState',
- 'karlnet_turbocell_txrate' => 'KarlNet-TurboCell-TxRate',
- 'lac_port' => 'LAC_Port',
- 'lac_port_type' => 'LAC_Port_Type',
- 'lac_port_typf' => 'LAC-Port-Type',
- 'lac_poru' => 'LAC-Port',
- 'lac_real_port' => 'LAC_Real_Port',
- 'lac_real_port_type' => 'LAC_Real_Port_Type',
- 'lac_real_port_typf' => 'LAC-Real-Port-Type',
- 'lac_real_poru' => 'LAC-Real-Port',
- 'ldap_group' => 'Ldap-Group',
- 'ldap_userdn' => 'Ldap-UserDn',
- 'le_admin_group' => 'LE-Admin-Group',
- 'le_advice_of_charge' => 'LE-Advice-of-Charge',
- 'le_connect_detail' => 'LE-Connect-Detail',
- 'le_ip_gateway' => 'LE-IP-Gateway',
- 'le_ip_pool' => 'LE-IP-Pool',
- 'le_ipsec_active_profile' => 'LE-IPSec-Active-Profile',
- 'le_ipsec_deny_action' => 'LE-IPSec-Deny-Action',
- 'le_ipsec_log_options' => 'LE-IPSec-Log-Options',
- 'le_ipsec_outsource_profi' => 'LE-IPSec-Outsource-Profile',
- 'le_ipsec_passive_profile' => 'LE-IPSec-Passive-Profile',
- 'le_modem_info' => 'LE-Modem-Info',
- 'le_multicast_client' => 'LE-Multicast-Client',
- 'le_nat_inmap' => 'LE-NAT-Inmap',
- 'le_nat_log_options' => 'LE-NAT-Log-Options',
- 'le_nat_other_session_tim' => 'LE-NAT-Other-Session-Timeout',
- 'le_nat_outmap' => 'LE-NAT-Outmap',
- 'le_nat_outsource_inmap' => 'LE-NAT-Outsource-Inmap',
- 'le_nat_outsource_outmap' => 'LE-NAT-Outsource-Outmap',
- 'le_nat_sess_dir_fail_act' => 'LE-NAT-Sess-Dir-Fail-Action',
- 'le_nat_tcp_session_timeo' => 'LE-NAT-TCP-Session-Timeout',
- 'le_terminate_detail' => 'LE-Terminate-Detail',
- 'lm_password' => 'LM-Password',
- 'local_web_acct_duration' => 'Local-Web-Acct-Duration',
- 'local_web_acct_interim_r' => 'Local-Web-Acct-Interim-Rx-Bytes',
- 'local_web_acct_interim_s' => 'Local-Web-Acct-Interim-Rx-Gigawords',
- 'local_web_acct_interim_t' => 'Local-Web-Acct-Interim-Tx-Bytes',
- 'local_web_acct_interim_u' => 'Local-Web-Acct-Interim-Tx-Gigawords',
- 'local_web_acct_interim_v' => 'Local-Web-Acct-Interim-Tx-Mgmt',
- 'local_web_acct_interim_w' => 'Local-Web-Acct-Interim-Rx-Mgmt',
- 'local_web_acct_rx_mgmt' => 'Local-Web-Acct-Rx-Mgmt',
- 'local_web_acct_time' => 'Local-Web-Acct-Time',
- 'local_web_acct_tx_mgmt' => 'Local-Web-Acct-Tx-Mgmt',
- 'local_web_border_router' => 'Local-Web-Border-Router',
- 'local_web_client_ip' => 'Local-Web-Client-Ip',
- 'local_web_reauth_counter' => 'Local-Web-Reauth-Counter',
- 'local_web_rx_limit' => 'Local-Web-Rx-Limit',
- 'local_web_tx_limit' => 'Local-Web-Tx-Limit',
- 'login_callback_number' => 'Login-Callback-Number',
- 'login_host' => 'Login-Host',
- 'login_ip_host' => 'Login-IP-Host',
- 'login_ipv6_host' => 'Login-IPv6-Host',
- 'login_lat_group' => 'Login-LAT-Group',
- 'login_lat_node' => 'Login-LAT-Node',
- 'login_lat_port' => 'Login-LAT-Port',
- 'login_lat_service' => 'Login-LAT-Service',
- 'login_port' => 'Login-Port',
- 'login_service' => 'Login-Service',
- 'login_tcp_port' => 'Login-TCP-Port',
- 'login_time' => 'Login-Time',
- 'mcast_maxgroups' => 'Mcast_MaxGroups',
- 'mcast_maxgroupt' => 'Mcast-MaxGroups',
- 'mcast_receive' => 'Mcast_Receive',
- 'mcast_receivf' => 'Mcast-Receive',
- 'mcast_send' => 'Mcast_Send',
- 'mcast_sene' => 'Mcast-Send',
- 'medium_type' => 'Medium_Type',
- 'medium_typf' => 'Medium-Type',
- 'menu' => 'Menu',
- 'merit_proxy_action' => 'Merit-Proxy-Action',
- 'merit_user_id' => 'Merit-User-Id',
- 'merit_user_realm' => 'Merit-User-Realm',
- 'message_authenticator' => 'Message-Authenticator',
- 'method' => 'method',
- 'mikrotik_group' => 'Mikrotik-Group',
- 'mikrotik_recv_limit' => 'Mikrotik-Recv-Limit',
- 'mikrotik_xmit_limit' => 'Mikrotik-Xmit-Limit',
- 'module_failure_message' => 'Module-Failure-Message',
- 'module_success_message' => 'Module-Success-Message',
- 'motorola_canopy_cirenabl' => 'Motorola-Canopy-CIRENABLE',
- 'motorola_canopy_dlba' => 'Motorola-Canopy-DLBA',
- 'motorola_canopy_enable' => 'Motorola-Canopy-Enable',
- 'motorola_canopy_higherbw' => 'Motorola-Canopy-HIGHERBW',
- 'motorola_canopy_hpcenabl' => 'Motorola-Canopy-HPCENABLE',
- 'motorola_canopy_hpsdldr' => 'Motorola-Canopy-HPSDLDR',
- 'motorola_canopy_hpsuldr' => 'Motorola-Canopy-HPSULDR',
- 'motorola_canopy_lpsdldr' => 'Motorola-Canopy-LPSDLDR',
- 'motorola_canopy_lpsuldr' => 'Motorola-Canopy-LPSULDR',
- 'motorola_canopy_sdldr' => 'Motorola-Canopy-SDLDR',
- 'motorola_canopy_shared_s' => 'Motorola-Canopy-Shared-Secret',
- 'motorola_canopy_suldr' => 'Motorola-Canopy-SULDR',
- 'motorola_canopy_ulba' => 'Motorola-Canopy-ULBA',
- 'ms_acct_auth_type' => 'MS-Acct-Auth-Type',
- 'ms_acct_eap_type' => 'MS-Acct-EAP-Type',
+ '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',
- 'ms_bap_usage' => 'MS-BAP-Usage',
- 'ms_chap2_cpw' => 'MS-CHAP2-CPW',
- 'ms_chap2_response' => 'MS-CHAP2-Response',
- 'ms_chap2_success' => 'MS-CHAP2-Success',
- 'ms_chap_challenge' => 'MS-CHAP-Challenge',
- 'ms_chap_cpw_1' => 'MS-CHAP-CPW-1',
- 'ms_chap_cpw_2' => 'MS-CHAP-CPW-2',
- 'ms_chap_domain' => 'MS-CHAP-Domain',
- 'ms_chap_error' => 'MS-CHAP-Error',
- 'ms_chap_lm_enc_pw' => 'MS-CHAP-LM-Enc-PW',
- 'ms_chap_mppe_keys' => 'MS-CHAP-MPPE-Keys',
- 'ms_chap_nt_enc_pw' => 'MS-CHAP-NT-Enc-PW',
- 'ms_chap_response' => 'MS-CHAP-Response',
- 'ms_chap_use_ntlm_auth' => 'MS-CHAP-Use-NTLM-Auth',
- 'ms_filter' => 'MS-Filter',
- 'ms_link_drop_time_limit' => 'MS-Link-Drop-Time-Limit',
- 'ms_link_utilization_thre' => 'MS-Link-Utilization-Threshold',
- 'ms_mppe_encryption_polic' => 'MS-MPPE-Encryption-Policy',
- 'ms_mppe_encryption_type' => 'MS-MPPE-Encryption-Type',
- 'ms_mppe_encryption_types' => 'MS-MPPE-Encryption-Types',
- 'ms_mppe_recv_key' => 'MS-MPPE-Recv-Key',
- 'ms_mppe_send_key' => 'MS-MPPE-Send-Key',
- 'ms_new_arap_password' => 'MS-New-ARAP-Password',
- 'ms_old_arap_password' => 'MS-Old-ARAP-Password',
- 'ms_primary_dns_server' => 'MS-Primary-DNS-Server',
- 'ms_primary_nbns_server' => 'MS-Primary-NBNS-Server',
- 'ms_ras_vendor' => 'MS-RAS-Vendor',
- 'ms_ras_version' => 'MS-RAS-Version',
- 'ms_secondary_dns_server' => 'MS-Secondary-DNS-Server',
- 'ms_secondary_nbns_server' => 'MS-Secondary-NBNS-Server',
- 'multi_link_flag' => 'Multi-Link-Flag',
- 'nas_identifier' => 'NAS-Identifier',
- 'nas_ip_address' => 'NAS-IP-Address',
- 'nas_ipv6_address' => 'NAS-IPv6-Address',
- 'nas_port' => 'NAS-Port',
- 'nas_port_id' => 'NAS-Port-Id',
- 'nas_port_type' => 'NAS-Port-Type',
- 'nas_real_port' => 'NAS_Real_Port',
- 'nas_real_poru' => 'NAS-Real-Port',
- 'navini_avpair' => 'Navini-AVPair',
- 'next_hop_dn' => 'next-hop-dn',
- 'next_hop_ip' => 'next-hop-ip',
- 'nn_data_rate' => 'NN-Data-Rate',
- 'nn_data_rate_ceiling' => 'NN-Data-Rate-Ceiling',
- 'nn_homenode' => 'NN-Homenode',
- 'nn_homeservice' => 'NN-Homeservice',
- 'nn_homeservice_name' => 'NN-Homeservice-Name',
- 'no_such_attribute' => 'No-Such-Attribute',
- 'nokia_charging_id' => 'Nokia-Charging-Id',
- 'nokia_ggsn_ip_address' => 'Nokia-GGSN-IP-Address',
- 'nokia_imsi' => 'Nokia-IMSI',
- 'nokia_prepaid_ind' => 'Nokia-Prepaid-Ind',
- 'nokia_sgsn_ip_address' => 'Nokia-SGSN-IP-Address',
- 'nomadix_bw_down' => 'Nomadix-Bw-Down',
- 'nomadix_bw_up' => 'Nomadix-Bw-Up',
- 'nomadix_config_url' => 'Nomadix-Config-URL',
- 'nomadix_endofsession' => 'Nomadix-EndofSession',
- 'nomadix_expiration' => 'Nomadix-Expiration',
- 'nomadix_goodbye_url' => 'Nomadix-Goodbye-URL',
- 'nomadix_ip_upsell' => 'Nomadix-IP-Upsell',
- 'nomadix_logoff_url' => 'Nomadix-Logoff-URL',
- 'nomadix_maxbytesdown' => 'Nomadix-MaxBytesDown',
- 'nomadix_maxbytesup' => 'Nomadix-MaxBytesUp',
- 'nomadix_net_vlan' => 'Nomadix-Net-VLAN',
- 'nomadix_subnet' => 'Nomadix-Subnet',
- 'nomadix_url_redirection' => 'Nomadix-URL-Redirection',
- 'ns_admin_privilege' => 'NS-Admin-Privilege',
- 'ns_mta_md5_password' => 'NS-MTA-MD5-Password',
- 'ns_primary_dns' => 'NS-Primary-DNS',
- 'ns_primary_wins' => 'NS-Primary-WINS',
- 'ns_secondary_dns' => 'NS-Secondary-DNS',
- 'ns_secondary_wins' => 'NS-Secondary-WINS',
- 'ns_user_group' => 'NS-User-Group',
- 'ns_vsys_name' => 'NS-VSYS-Name',
- 'nt_password' => 'NT-Password',
- 'ntlm_user_name' => 'NTLM-User-Name',
- 'old_password' => 'Old-Password',
- 'outgoing_req_uri' => 'outgoing-req-uri',
- 'packet_dst_port' => 'Packet-Dst-Port',
- 'packet_type' => 'Packet-Type',
- 'pam_auth' => 'Pam-Auth',
- 'password' => 'Password',
- 'password_retry' => 'Password-Retry',
- 'police_burst' => 'Police_Burst',
- 'police_bursu' => 'Police-Burst',
- 'police_rate' => 'Police_Rate',
- 'police_ratf' => 'Police-Rate',
- 'pool_name' => 'Pool-Name',
- 'port_limit' => 'Port-Limit',
- 'port_message' => 'Port-Message',
- 'post_auth_type' => 'Post-Auth-Type',
- 'post_proxy_type' => 'Post-Proxy-Type',
- 'postauth_type' => 'PostAuth-Type',
- 'pppoe_motm' => 'PPPOE_MOTM',
- 'pppoe_motn' => 'PPPOE-MOTM',
- 'pppoe_url' => 'PPPOE_URL',
- 'pppoe_urm' => 'PPPOE-URL',
- 'pre_acct_type' => 'Pre-Acct-Type',
- 'pre_proxy_type' => 'Pre-Proxy-Type',
- 'prefix' => 'Prefix',
- 'prev_hop_ip' => 'prev-hop-ip',
- 'prev_hop_via' => 'prev-hop-via',
- 'prompt' => 'Prompt',
- 'propel_accelerate' => 'Propel-Accelerate',
- 'propel_client_ip_address' => 'Propel-Client-IP-Address',
- 'propel_client_nas_ip_add' => 'Propel-Client-NAS-IP-Address',
- 'propel_client_source_id' => 'Propel-Client-Source-ID',
- 'propel_dialed_digits' => 'Propel-Dialed-Digits',
- 'proxy_state' => 'Proxy-State',
- 'proxy_to_realm' => 'Proxy-To-Realm',
- 'pvc_circuit_padding' => 'PVC_Circuit_Padding',
- 'pvc_circuit_paddinh' => 'PVC-Circuit-Padding',
- 'pvc_encapsulation_type' => 'PVC_Encapsulation_Type',
- 'pvc_encapsulation_typf' => 'PVC-Encapsulation-Type',
- 'pvc_profile_name' => 'PVC_Profile_Name',
- 'pvc_profile_namf' => 'PVC-Profile-Name',
- 'quintum_avpair' => 'Quintum-AVPair',
- 'quintum_h323_billing_mod' => 'Quintum-h323-billing-model',
+ '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',
- 'quintum_h323_call_type' => 'Quintum-h323-call-type',
- 'quintum_h323_conf_id' => 'Quintum-h323-conf-id',
- 'quintum_h323_connect_tim' => 'Quintum-h323-connect-time',
+ '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',
+ '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',
+ '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',
- 'quintum_h323_credit_time' => 'Quintum-h323-credit-time',
- 'quintum_h323_currency_ty' => 'Quintum-h323-currency-type',
- 'quintum_h323_disconnect_' => 'Quintum-h323-disconnect-time',
- 'quintum_h323_disconnecta' => 'Quintum-h323-disconnect-cause',
- 'quintum_h323_gw_id' => 'Quintum-h323-gw-id',
- 'quintum_h323_incoming_co' => 'Quintum-h323-incoming-conf-id',
- 'quintum_h323_preferred_l' => 'Quintum-h323-preferred-lang',
- 'quintum_h323_prompt_id' => 'Quintum-h323-prompt-id',
+ '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_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',
+ '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',
+ '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',
+ 'le_nat_tcp_session_timeo' => 'LE-NAT-TCP-Session-Timeout',
'quintum_h323_redirect_ip' => 'Quintum-h323-redirect-ip-address',
- 'quintum_h323_redirect_nu' => 'Quintum-h323-redirect-number',
+ 'ms_acct_eap_type' => 'MS-Acct-EAP-Type',
+ 'usr_rmmie_x2_status' => 'USR-RMMIE-x2-Status',
+ 'x_ascend_user_acct_type' => 'X-Ascend-User-Acct-Type',
+ 'shiva_customer_id' => 'Shiva-Customer-Id',
+ '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',
+ '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',
+ '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_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',
+ 'cabletron_protocol_calla' => 'Cabletron-Protocol-Callable',
+ 'cisco_data_rate' => 'Cisco-Data-Rate',
+ 'usr_primary_dns_server' => 'USR-Primary_DNS_Server',
+ 'juniper_deny_configurati' => 'Juniper-Deny-Configuration',
+ 'ascend_target_util' => 'Ascend-Target-Util',
+ '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',
+ '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',
+ 'tunnel_medium_type' => 'Tunnel-Medium-Type',
'quintum_h323_remote_addr' => 'Quintum-h323-remote-address',
- 'quintum_h323_return_code' => 'Quintum-h323-return-code',
- 'quintum_h323_setup_time' => 'Quintum-h323-setup-time',
- 'quintum_h323_time_and_da' => 'Quintum-h323-time-and-day',
- 'quintum_h323_voice_quali' => 'Quintum-h323-voice-quality',
- 'quintum_nas_port' => 'Quintum-NAS-Port',
- 'rate_limit_burst' => 'Rate_Limit_Burst',
- 'rate_limit_bursu' => 'Rate-Limit-Burst',
- 'rate_limit_rate' => 'Rate_Limit_Rate',
- 'rate_limit_ratf' => 'Rate-Limit-Rate',
- 'realm' => 'Realm',
- 'redcreek_tunneled_dns_se' => 'RedCreek-Tunneled-DNS-Server',
- 'redcreek_tunneled_domain' => 'RedCreek-Tunneled-DomainName',
- 'redcreek_tunneled_gatewa' => 'RedCreek-Tunneled-Gateway',
- 'redcreek_tunneled_hostna' => 'RedCreek-Tunneled-HostName',
- 'redcreek_tunneled_ip_add' => 'RedCreek-Tunneled-IP-Addr',
- 'redcreek_tunneled_ip_net' => 'RedCreek-Tunneled-IP-Netmask',
- 'redcreek_tunneled_search' => 'RedCreek-Tunneled-Search-List',
+ 'acc_callback_delay' => 'Acc-Callback-Delay',
+ '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',
+ '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',
+ 'tunnel_police_bursu' => 'Tunnel_Police_Burst',
'redcreek_tunneled_wins_s' => 'RedCreek-Tunneled-WINS-Server1',
- 'redcreek_tunneled_wins_t' => 'RedCreek-Tunneled-WINS-Server2',
- 'replicate_to_realm' => 'Replicate-To-Realm',
- 'reply_message' => 'Reply-Message',
- 'response_packet_type' => 'Response-Packet-Type',
- 'rewrite_rule' => 'Rewrite-Rule',
- 'sdx_service_name' => 'Sdx-Service-Name',
- 'sdx_session_volume_quota' => 'Sdx-Session-Volume-Quota',
- 'sdx_tunnel_disconnect_ca' => 'Sdx-Tunnel-Disconnect-Cause-Info',
- 'service_type' => 'Service-Type',
- 'session' => 'Session',
- 'session_error_code' => 'Session_Error_Code',
- 'session_error_codf' => 'Session-Error-Code',
- 'session_error_msg' => 'Session_Error_Msg',
- 'session_error_msh' => 'Session-Error-Msg',
- 'session_protocol' => 'session-protocol',
- 'session_timeout' => 'Session-Timeout',
- 'session_type' => 'Session-Type',
- 'shasta_service_profile' => 'Shasta-Service-Profile',
- 'shasta_user_privilege' => 'Shasta-User-Privilege',
- 'shasta_vpn_name' => 'Shasta-VPN-Name',
- 'shiva_acct_serv_switch' => 'Shiva-Acct-Serv-Switch',
- 'shiva_called_number' => 'Shiva-Called-Number',
- 'shiva_calling_number' => 'Shiva-Calling-Number',
- 'shiva_compression_type' => 'Shiva-Compression-Type',
- 'shiva_connect_reason' => 'Shiva-Connect-Reason',
- 'shiva_customer_id' => 'Shiva-Customer-Id',
- 'shiva_disconnect_reason' => 'Shiva-Disconnect-Reason',
- 'shiva_event_flags' => 'Shiva-Event-Flags',
- 'shiva_function' => 'Shiva-Function',
- 'shiva_link_protocol' => 'Shiva-Link-Protocol',
- 'shiva_link_speed' => 'Shiva-Link-Speed',
- 'shiva_links_in_bundle' => 'Shiva-Links-In-Bundle',
- 'shiva_network_protocols' => 'Shiva-Network-Protocols',
- 'shiva_session_id' => 'Shiva-Session-Id',
- 'shiva_type_of_service' => 'Shiva-Type-Of-Service',
- 'shiva_user_attributes' => 'Shiva-User-Attributes',
- 'simultaneous_use' => 'Simultaneous-Use',
- 'sip_from' => 'Sip-From',
- 'sip_hdr' => 'sip-hdr',
- 'sip_method' => 'Sip-Method',
- 'sip_to' => 'Sip-To',
- 'sip_translated_request_u' => 'Sip-Translated-Request-URI',
- 'smb_account_ctrl' => 'SMB-Account-CTRL',
- 'smb_account_ctrl_text' => 'SMB-Account-CTRL-TEXT',
- 'sonicwall_user_group' => 'SonicWall-User-Group',
- 'sonicwall_user_privilege' => 'SonicWall-User-Privilege',
- 'source_validation' => 'Source_Validation',
- 'source_validatioo' => 'Source-Validation',
- 'sql_group' => 'Sql-Group',
- 'sql_user_name' => 'SQL-User-Name',
- 'ss3_firewall_user_privil' => 'SS3-Firewall-User-Privilege',
- 'st_acct_vc_connection_id' => 'ST-Acct-VC-Connection-Id',
- 'st_policy_name' => 'ST-Policy-Name',
- 'st_primary_dns_server' => 'ST-Primary-DNS-Server',
- 'st_primary_nbns_server' => 'ST-Primary-NBNS-Server',
- 'st_secondary_dns_server' => 'ST-Secondary-DNS-Server',
- 'st_secondary_nbns_server' => 'ST-Secondary-NBNS-Server',
- 'st_service_domain' => 'ST-Service-Domain',
- 'st_service_name' => 'ST-Service-Name',
- 'state' => 'State',
- 'strip_user_name' => 'Strip-User-Name',
- 'stripped_user_name' => 'Stripped-User-Name',
- 'subscriber' => 'subscriber',
- 'suffix' => 'Suffix',
- 'telebit_accounting_info' => 'Telebit-Accounting-Info',
- 'telebit_activate_command' => 'Telebit-Activate-Command',
- 'telebit_login_command' => 'Telebit-Login-Command',
- 'telebit_port_name' => 'Telebit-Port-Name',
- 'termination_action' => 'Termination-Action',
- 'termination_menu' => 'Termination-Menu',
- 'trapeze_encryption_type' => 'Trapeze-Encryption-Type',
- 'trapeze_end_date' => 'Trapeze-End-Date',
- 'trapeze_mobility_profile' => 'Trapeze-Mobility-Profile',
- 'trapeze_ssid' => 'Trapeze-SSID',
- 'trapeze_start_date' => 'Trapeze-Start-Date',
- 'trapeze_time_of_day' => 'Trapeze-Time-Of-Day',
- 'trapeze_url' => 'Trapeze-URL',
- 'trapeze_vlan_name' => 'Trapeze-VLAN-Name',
- 'tty_level_max' => 'TTY_Level_Max',
- 'tty_level_may' => 'TTY-Level-Max',
- 'tty_level_start' => 'TTY_Level_Start',
- 'tty_level_staru' => 'TTY-Level-Start',
- 'tunnel_algorithm' => 'Tunnel_Algorithm',
- 'tunnel_algorithn' => 'Tunnel-Algorithm',
- 'tunnel_assignment_id' => 'Tunnel-Assignment-Id',
- 'tunnel_client_auth_id' => 'Tunnel-Client-Auth-Id',
- 'tunnel_client_endpoint' => 'Tunnel-Client-Endpoint',
- 'tunnel_cmd_timeout' => 'Tunnel_Cmd_Timeout',
- 'tunnel_cmd_timeouu' => 'Tunnel-Cmd-Timeout',
- 'tunnel_connection_id' => 'Tunnel-Connection-Id',
- 'tunnel_context' => 'Tunnel_Context',
- 'tunnel_contexu' => 'Tunnel-Context',
- 'tunnel_deadtime' => 'Tunnel_Deadtime',
- 'tunnel_deadtimf' => 'Tunnel-Deadtime',
- 'tunnel_dnis' => 'Tunnel_DNIS',
- 'tunnel_dnit' => 'Tunnel-DNIS',
- 'tunnel_domain' => 'Tunnel_Domain',
- 'tunnel_domaio' => 'Tunnel-Domain',
- 'tunnel_function' => 'Tunnel_Function',
- 'tunnel_functioo' => 'Tunnel-Function',
- 'tunnel_group' => 'Tunnel_Group',
- 'tunnel_grouq' => 'Tunnel-Group',
- 'tunnel_l2f_second_passwo' => 'Tunnel_L2F_Second_Password',
- 'tunnel_l2f_second_passwp' => 'Tunnel-L2F-Second-Password',
- 'tunnel_local_name' => 'Tunnel_Local_Name',
- 'tunnel_local_namf' => 'Tunnel-Local-Name',
- 'tunnel_max_sessions' => 'Tunnel_Max_Sessions',
- 'tunnel_max_sessiont' => 'Tunnel-Max-Sessions',
- 'tunnel_max_tunnels' => 'Tunnel_Max_Tunnels',
- 'tunnel_max_tunnelt' => 'Tunnel-Max-Tunnels',
- 'tunnel_medium_type' => 'Tunnel-Medium-Type',
- 'tunnel_password' => 'Tunnel-Password',
- 'tunnel_police_burst' => 'Tunnel_Police_Burst',
- 'tunnel_police_bursu' => 'Tunnel-Police-Burst',
- 'tunnel_police_rate' => 'Tunnel_Police_Rate',
- 'tunnel_police_ratf' => 'Tunnel-Police-Rate',
- 'tunnel_preference' => 'Tunnel-Preference',
- 'tunnel_private_group_id' => 'Tunnel-Private-Group-Id',
- 'tunnel_rate_limit_burst' => 'Tunnel_Rate_Limit_Burst',
- 'tunnel_rate_limit_bursu' => 'Tunnel-Rate-Limit-Burst',
- 'tunnel_rate_limit_rate' => 'Tunnel_Rate_Limit_Rate',
- 'tunnel_rate_limit_ratf' => 'Tunnel-Rate-Limit-Rate',
- 'tunnel_remote_name' => 'Tunnel_Remote_Name',
- 'tunnel_remote_namf' => 'Tunnel-Remote-Name',
- 'tunnel_retransmit' => 'Tunnel_Retransmit',
- 'tunnel_retransmiu' => 'Tunnel-Retransmit',
- 'tunnel_server_auth_id' => 'Tunnel-Server-Auth-Id',
- 'tunnel_server_endpoint' => 'Tunnel-Server-Endpoint',
- 'tunnel_session_auth' => 'Tunnel_Session_Auth',
- 'tunnel_session_auth_ctx' => 'Tunnel_Session_Auth_Ctx',
- 'tunnel_session_auth_cty' => 'Tunnel-Session-Auth-Ctx',
- 'tunnel_session_auth_serv' => 'Tunnel_Session_Auth_Service_Grp',
- 'tunnel_session_auth_serw' => 'Tunnel-Session-Auth-Service-Grp',
- 'tunnel_session_auti' => 'Tunnel-Session-Auth',
- 'tunnel_type' => 'Tunnel-Type',
- 'tunnel_window' => 'Tunnel_Window',
- 'tunnel_windox' => 'Tunnel-Window',
- 'unix_ftp_gid' => 'Unix-FTP-GID',
- 'unix_ftp_group_ids' => 'Unix-FTP-Group-Ids',
- 'unix_ftp_group_names' => 'Unix-FTP-Group-Names',
- 'unix_ftp_home' => 'Unix-FTP-Home',
- 'unix_ftp_shell' => 'Unix-FTP-Shell',
- 'unix_ftp_uid' => 'Unix-FTP-UID',
- 'user_category' => 'User-Category',
- 'user_name' => 'User-Name',
- 'user_name_is_star' => 'User-Name-Is-Star',
- 'user_password' => 'User-Password',
- 'user_profile' => 'User-Profile',
- 'user_service_type' => 'User-Service-Type',
- 'usr_accm_type' => 'USR-ACCM-Type',
- 'usr_acct_reason_code' => 'USR-Acct-Reason-Code',
- 'usr_actual_voltage' => 'USR-Actual-Voltage',
- 'usr_appletalk' => 'USR-Appletalk',
- 'usr_appletalk_network_ra' => 'USR-Appletalk-Network-Range',
+ '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',
+ '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',
+ 'aat_client_primary_wins_' => 'AAT-Client-Primary-WINS-NBNS',
+ 'h323_currency' => 'h323-currency',
+ 'password' => 'Password',
+ 'le_nat_log_options' => 'LE-NAT-Log-Options',
+ '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',
+ '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',
+ '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',
+ 'ms_ras_version' => 'MS-RAS-Version',
+ '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',
+ 'callback_id' => 'Callback-Id',
+ 'framed_ipx_network' => 'Framed-IPX-Network',
+ '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',
+ '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_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',
+ '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',
+ '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',
- 'usr_at_call_output_filte' => 'USR-AT-Call-Output-Filter',
- 'usr_at_input_filter' => 'USR-AT-Input-Filter',
- 'usr_at_output_filter' => 'USR-AT-Output-Filter',
- 'usr_at_rtmp_input_filter' => 'USR-AT-RTMP-Input-Filter',
- 'usr_at_rtmp_output_filte' => 'USR-AT-RTMP-Output-Filter',
- 'usr_at_zip_input_filter' => 'USR-AT-Zip-Input-Filter',
- 'usr_at_zip_output_filter' => 'USR-AT-Zip-Output-Filter',
- 'usr_auth_mode' => 'USR-Auth-Mode',
- 'usr_back_channel_data_ra' => 'USR-Back-Channel-Data-Rate',
- 'usr_bearer_capabilities' => 'USR-Bearer-Capabilities',
- 'usr_block_error_count_li' => 'USR-Block-Error-Count-Limit',
- 'usr_blocks_received' => 'USR-Blocks-Received',
- 'usr_blocks_resent' => 'USR-Blocks-Resent',
- 'usr_blocks_sent' => 'USR-Blocks-Sent',
- 'usr_bridging' => 'USR-Bridging',
- 'usr_call_arrival_in_gmt' => 'USR-Call-Arrival-in-GMT',
- 'usr_call_arrival_time' => 'USR-Call-Arrival-Time',
- 'usr_call_connect_in_gmt' => 'USR-Call-Connect-in-GMT',
- 'usr_call_connecting_time' => 'USR-Call-Connecting-Time',
- 'usr_call_end_date_time' => 'USR-Call-End-Date-Time',
- 'usr_call_end_time' => 'USR-Call-End-Time',
- 'usr_call_error_code' => 'USR-Call-Error-Code',
- 'usr_call_event_code' => 'USR-Call-Event-Code',
- 'usr_call_reference_numbe' => 'USR-Call-Reference-Number',
- 'usr_call_start_date_time' => 'USR-Call-Start-Date-Time',
- 'usr_call_terminate_in_gm' => 'USR-Call-Terminate-in-GMT',
- 'usr_call_type' => 'USR-Call-Type',
- 'usr_callback_type' => 'USR-Callback-Type',
- 'usr_called_party_number' => 'USR-Called-Party-Number',
- 'usr_calling_party_number' => 'USR-Calling-Party-Number',
- 'usr_card_type' => 'USR-Card-Type',
- 'usr_ccp_algorithm' => 'USR-CCP-Algorithm',
- 'usr_cdma_call_reference_' => 'USR-CDMA-Call-Reference-Number',
- 'usr_channel' => 'USR-Channel',
- 'usr_channel_connected_to' => 'USR-Channel-Connected-To',
- 'usr_channel_decrement' => 'USR-Channel-Decrement',
- 'usr_channel_expansion' => 'USR-Channel-Expansion',
- 'usr_characters_received' => 'USR-Characters-Received',
- 'usr_characters_sent' => 'USR-Characters-Sent',
- 'usr_chassis_call_channel' => 'USR-Chassis-Call-Channel',
- 'usr_chassis_call_slot' => 'USR-Chassis-Call-Slot',
- 'usr_chassis_call_span' => 'USR-Chassis-Call-Span',
- 'usr_chassis_slot' => 'USR-Chassis-Slot',
- 'usr_chassis_temp_thresho' => 'USR-Chassis-Temp-Threshold',
- 'usr_chassis_temperature' => 'USR-Chassis-Temperature',
- 'usr_chat_script_name' => 'USR-Chat-Script-Name',
- 'usr_compression_algorith' => 'USR-Compression-Algorithm',
- 'usr_compression_reset_mo' => 'USR-Compression-Reset-Mode',
- 'usr_compression_type' => 'USR-Compression-Type',
- 'usr_connect_speed' => 'USR-Connect-Speed',
- 'usr_connect_term_reason' => 'USR-Connect-Term-Reason',
- 'usr_connect_time' => 'USR-Connect-Time',
- 'usr_connect_time_limit' => 'USR-Connect-Time-Limit',
- 'usr_cusr_hat_script_rule' => 'USR-CUSR-hat-Script-Rules',
- 'usr_default_dte_data_rat' => 'USR-Default-DTE-Data-Rate',
- 'usr_device_connected_to' => 'USR-Device-Connected-To',
- 'usr_disconnect_cause_ind' => 'USR-Disconnect-Cause-Indicator',
- 'usr_dnis_reauthenticatio' => 'USR-DNIS-ReAuthentication',
- 'usr_ds0' => 'USR-DS0',
- 'usr_ds0s' => 'USR-DS0s',
- 'usr_dte_data_idle_timout' => 'USR-DTE-Data-Idle-Timout',
- 'usr_dte_ring_no_answer_l' => 'USR-DTE-Ring-No-Answer-Limit',
- 'usr_dtr_false_timeout' => 'USR-DTR-False-Timeout',
- 'usr_dtr_true_timeout' => 'USR-DTR-True-Timeout',
- 'usr_end_time' => 'USR-End-Time',
- 'usr_equalization_type' => 'USR-Equalization-Type',
- 'usr_esn' => 'USR-ESN',
- 'usr_et_bridge_call_outpu' => 'USR-ET-Bridge-Call-Output-Filte',
- 'usr_et_bridge_input_filt' => 'USR-ET-Bridge-Input-Filter',
- 'usr_et_bridge_output_fil' => 'USR-ET-Bridge-Output-Filter',
- 'usr_event_date_time' => 'USR-Event-Date-Time',
- 'usr_event_id' => 'USR-Event-Id',
- 'usr_expansion_algorithm' => 'USR-Expansion-Algorithm',
- 'usr_expected_voltage' => 'USR-Expected-Voltage',
- 'usr_failure_to_connect_r' => 'USR-Failure-to-Connect-Reason',
- 'usr_fallback_enabled' => 'USR-Fallback-Enabled',
- 'usr_fallback_limit' => 'USR-Fallback-Limit',
- 'usr_filter_zones' => 'USR-Filter-Zones',
- 'usr_final_rx_link_data_r' => 'USR-Final-Rx-Link-Data-Rate',
- 'usr_final_tx_link_data_r' => 'USR-Final-Tx-Link-Data-Rate',
- 'usr_framed_ip_address_po' => 'USR-Framed_IP_Address_Pool_Name',
- 'usr_framed_ipx_route' => 'USR-Framed-IPX-Route',
- 'usr_gateway_ip_address' => 'USR-Gateway-IP-Address',
- 'usr_harc_disconnect_code' => 'USR-HARC-Disconnect-Code',
- 'usr_host_type' => 'USR-Host-Type',
- 'usr_ids0_call_type' => 'USR-IDS0-Call-Type',
- 'usr_igmp_maximum_respons' => 'USR-IGMP-Maximum-Response-Time',
- 'usr_igmp_query_interval' => 'USR-IGMP-Query-Interval',
- 'usr_igmp_robustness' => 'USR-IGMP-Robustness',
- 'usr_igmp_routing' => 'USR-IGMP-Routing',
- 'usr_igmp_version' => 'USR-IGMP-Version',
- 'usr_imsi' => 'USR-IMSI',
- 'usr_initial_rx_link_data' => 'USR-Initial-Rx-Link-Data-Rate',
- 'usr_initial_tx_link_data' => 'USR-Initial-Tx-Link-Data-Rate',
- 'usr_interface_index' => 'USR-Interface-Index',
- 'usr_ip' => 'USR-IP',
- 'usr_ip_call_input_filter' => 'USR-IP-Call-Input-Filter',
- 'usr_ip_call_output_filte' => 'USR-IP-Call-Output-Filter',
- 'usr_ip_default_route_opt' => 'USR-IP-Default-Route-Option',
- 'usr_ip_rip_input_filter' => 'USR-IP-RIP-Input-Filter',
- 'usr_ip_rip_output_filter' => 'USR-IP-RIP-Output-Filter',
- 'usr_ip_rip_policies' => 'USR-IP-RIP-Policies',
- 'usr_ip_rip_simple_auth_p' => 'USR-IP-RIP-Simple-Auth-Password',
- 'usr_ip_saa_filter' => 'USR-IP-SAA-Filter',
- 'usr_ipx' => 'USR-IPX',
- 'usr_ipx_call_input_filte' => 'USR-IPX-Call-Input-Filter',
- 'usr_ipx_call_output_filt' => 'USR-IPX-Call-Output-Filter',
- 'usr_ipx_rip_input_filter' => 'USR-IPX-RIP-Input-Filter',
- 'usr_ipx_rip_output_filte' => 'USR-IPX-RIP-Output-Filter',
- 'usr_ipx_routing' => 'USR-IPX-Routing',
- 'usr_ipx_wan' => 'USR-IPX-WAN',
- 'usr_iwf_call_identifier' => 'USR-IWF-Call-Identifier',
- 'usr_iwf_ip_address' => 'USR-IWF-IP-Address',
- 'usr_keypress_timeout' => 'USR-Keypress-Timeout',
- 'usr_last_callers_number_' => 'USR-Last-Callers-Number-ANI',
- 'usr_last_number_dialed_i' => 'USR-Last-Number-Dialed-In-DNIS',
- 'usr_last_number_dialed_o' => 'USR-Last-Number-Dialed-Out',
- 'usr_line_reversals' => 'USR-Line-Reversals',
- 'usr_local_framed_ip_addr' => 'USR-Local-Framed-IP-Addr',
- 'usr_local_ip_address' => 'USR-Local-IP-Address',
- 'usr_log_filter_packets' => 'USR-Log-Filter-Packets',
- 'usr_max_channels' => 'USR-Max-Channels',
- 'usr_mbi_ct_bchannel_used' => 'USR-Mbi_Ct_BChannel_Used',
- 'usr_mbi_ct_pri_card_slot' => 'USR-Mbi_Ct_PRI_Card_Slot',
- 'usr_mbi_ct_pri_card_span' => 'USR-Mbi_Ct_PRI_Card_Span_Line',
- 'usr_mbi_ct_tdm_time_slot' => 'USR-Mbi_Ct_TDM_Time_Slot',
- 'usr_mic' => 'USR-MIC',
- 'usr_min_compression_size' => 'USR-Min-Compression-Size',
- 'usr_mobile_ip_address' => 'USR-Mobile-IP-Address',
- 'usr_mobile_numbytes_rxed' => 'USR-Mobile-NumBytes-Rxed',
- 'usr_mobile_numbytes_txed' => 'USR-Mobile-NumBytes-Txed',
- 'usr_mobileip_home_agent_' => 'USR-MobileIP-Home-Agent-Address',
- 'usr_modem_group' => 'USR-Modem-Group',
- 'usr_modem_setup_time' => 'USR-Modem-Setup-Time',
- 'usr_modem_training_time' => 'USR-Modem-Training-Time',
- 'usr_modulation_type' => 'USR-Modulation-Type',
- 'usr_mp_edo' => 'USR-MP-EDO',
- 'usr_mp_edo_hiper' => 'USR-MP-EDO-HIPER',
- 'usr_mp_mrru' => 'USR-MP-MRRU',
- 'usr_mpip_tunnel_originat' => 'USR-MPIP-Tunnel-Originator',
- 'usr_multicast_forwarding' => 'USR-Multicast-Forwarding',
- 'usr_multicast_proxy' => 'USR-Multicast-Proxy',
- 'usr_multicast_receive' => 'USR-Multicast-Receive',
- 'usr_nas_type' => 'USR-NAS-Type',
- 'usr_nfas_id' => 'USR-NFAS-ID',
- 'usr_num_fax_pages_proces' => 'USR-Num-Fax-Pages-Processed',
- 'usr_number_of_blers' => 'USR-Number-of-Blers',
- 'usr_number_of_characters' => 'USR-Number-Of-Characters-Lost',
- 'usr_number_of_fallbacks' => 'USR-Number-of-Fallbacks',
- 'usr_number_of_link_naks' => 'USR-Number-of-Link-NAKs',
- 'usr_number_of_link_timeo' => 'USR-Number-of-Link-Timeouts',
- 'usr_number_of_rings_limi' => 'USR-Number-of-Rings-Limit',
- 'usr_number_of_upshifts' => 'USR-Number-of-Upshifts',
- 'usr_orig_nas_type' => 'USR-Orig-NAS-Type',
- 'usr_originate_answer_mod' => 'USR-Originate-Answer-Mode',
- 'usr_ospf_addressless_ind' => 'USR-OSPF-Addressless-Index',
- 'usr_packet_bus_session' => 'USR-Packet-Bus-Session',
- 'usr_physical_state' => 'USR-Physical-State',
- 'usr_port_tap' => 'USR-Port-Tap',
- 'usr_port_tap_address' => 'USR-Port-Tap-Address',
- 'usr_port_tap_facility' => 'USR-Port-Tap-Facility',
- 'usr_port_tap_format' => 'USR-Port-Tap-Format',
- 'usr_port_tap_output' => 'USR-Port-Tap-Output',
- 'usr_port_tap_priority' => 'USR-Port-Tap-Priority',
- 'usr_power_supply_number' => 'USR-Power-Supply-Number',
- 'usr_primary_dns_server' => 'USR-Primary_DNS_Server',
- 'usr_primary_nbns_server' => 'USR-Primary_NBNS_Server',
- 'usr_pw_cutoff' => 'USR-PW_Cutoff',
- 'usr_pw_framed_routing_v2' => 'USR-PW_Framed_Routing_V2',
- 'usr_pw_index' => 'USR-PW_Index',
- 'usr_pw_packet' => 'USR-PW_Packet',
- 'usr_pw_tunnel_authentica' => 'USR-PW_Tunnel_Authentication',
- 'usr_pw_usr_ifilter_ip' => 'USR-PW_USR_IFilter_IP',
- 'usr_pw_usr_ifilter_ipx' => 'USR-PW_USR_IFilter_IPX',
- 'usr_pw_usr_ofilter_ip' => 'USR-PW_USR_OFilter_IP',
- 'usr_pw_usr_ofilter_ipx' => 'USR-PW_USR_OFilter_IPX',
- 'usr_pw_usr_ofilter_sap' => 'USR-PW_USR_OFilter_SAP',
- 'usr_pw_vpn_gateway' => 'USR-PW_VPN_Gateway',
- 'usr_pw_vpn_id' => 'USR-PW_VPN_ID',
- 'usr_pw_vpn_name' => 'USR-PW_VPN_Name',
- 'usr_pw_vpn_neighbor' => 'USR-PW_VPN_Neighbor',
- 'usr_q931_call_reference_' => 'USR-Q931-Call-Reference-Value',
- 'usr_rad_dvmrp_metric' => 'USR-Rad-Dvmrp-Metric',
- 'usr_rad_location_type' => 'USR-Rad-Location-Type',
- 'usr_rad_multicast_routin' => 'USR-Rad-Multicast-Routing-Ttl',
- 'usr_rad_multicast_routio' => 'USR-Rad-Multicast-Routing-RtLim',
- 'usr_rad_multicast_routip' => 'USR-Rad-Multicast-Routing-Proto',
+ 'framed_ipv6_pool' => 'Framed-IPv6-Pool',
+ 'ascend_qos_downstream' => 'Ascend-QOS-Downstream',
+ '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',
'usr_rad_multicast_routiq' => 'USR-Rad-Multicast-Routing-Bound',
- 'usr_re_chap_timeout' => 'USR-Re-Chap-Timeout',
- 'usr_receive_acc_map' => 'USR-Receive-Acc-Map',
- 'usr_reply_script1' => 'USR-Reply-Script1',
- 'usr_reply_script2' => 'USR-Reply-Script2',
- 'usr_reply_script3' => 'USR-Reply-Script3',
- 'usr_reply_script4' => 'USR-Reply-Script4',
- 'usr_reply_script5' => 'USR-Reply-Script5',
- 'usr_reply_script6' => 'USR-Reply-Script6',
- 'usr_request_type' => 'USR-Request-Type',
- 'usr_retrains_granted' => 'USR-Retrains-Granted',
- 'usr_retrains_requested' => 'USR-Retrains-Requested',
- 'usr_rmmie_firmware_build' => 'USR-RMMIE-Firmware-Build-Date',
- 'usr_rmmie_firmware_versi' => 'USR-RMMIE-Firmware-Version',
- 'usr_rmmie_last_update_ev' => 'USR-RMMIE-Last-Update-Event',
- 'usr_rmmie_last_update_ti' => 'USR-RMMIE-Last-Update-Time',
- 'usr_rmmie_manufacturer_i' => 'USR-RMMIE-Manufacturer-ID',
- 'usr_rmmie_num_of_updates' => 'USR-RMMIE-Num-Of-Updates',
- 'usr_rmmie_planned_discon' => 'USR-RMMIE-Planned-Disconnect',
- 'usr_rmmie_product_code' => 'USR-RMMIE-Product-Code',
- 'usr_rmmie_pwrlvl_farecho' => 'USR-RMMIE-PwrLvl-FarEcho-Canc',
- 'usr_rmmie_pwrlvl_nearech' => 'USR-RMMIE-PwrLvl-NearEcho-Canc',
- 'usr_rmmie_pwrlvl_noise_l' => 'USR-RMMIE-PwrLvl-Noise-Lvl',
- 'usr_rmmie_pwrlvl_xmit_lv' => 'USR-RMMIE-PwrLvl-Xmit-Lvl',
- 'usr_rmmie_rcv_pwrlvl_330' => 'USR-RMMIE-Rcv-PwrLvl-3300Hz',
- 'usr_rmmie_rcv_pwrlvl_375' => 'USR-RMMIE-Rcv-PwrLvl-3750Hz',
- 'usr_rmmie_rcv_tot_pwrlvl' => 'USR-RMMIE-Rcv-Tot-PwrLvl',
- 'usr_rmmie_serial_number' => 'USR-RMMIE-Serial-Number',
- 'usr_rmmie_status' => 'USR-RMMIE-Status',
- 'usr_rmmie_x2_status' => 'USR-RMMIE-x2-Status',
- 'usr_routing_protocol' => 'USR-Routing-Protocol',
- 'usr_sap_filter_in' => 'USR-SAP-Filter-In',
- 'usr_secondary_dns_server' => 'USR-Secondary_DNS_Server',
- 'usr_secondary_nbns_serve' => 'USR-Secondary_NBNS_Server',
- 'usr_security_login_limit' => 'USR-Security-Login-Limit',
- 'usr_security_resp_limit' => 'USR-Security-Resp-Limit',
- 'usr_send_name' => 'USR-Send-Name',
- 'usr_send_password' => 'USR-Send-Password',
- 'usr_send_script1' => 'USR-Send-Script1',
- 'usr_send_script2' => 'USR-Send-Script2',
- 'usr_send_script3' => 'USR-Send-Script3',
- 'usr_send_script4' => 'USR-Send-Script4',
- 'usr_send_script5' => 'USR-Send-Script5',
- 'usr_send_script6' => 'USR-Send-Script6',
- 'usr_server_time' => 'USR-Server-Time',
- 'usr_service_option' => 'USR-Service-Option',
- 'usr_simplified_mnp_level' => 'USR-Simplified-MNP-Levels',
- 'usr_simplified_v42bis_us' => 'USR-Simplified-V42bis-Usage',
- 'usr_slot_connected_to' => 'USR-Slot-Connected-To',
- 'usr_speed_of_connection' => 'USR-Speed-Of-Connection',
- 'usr_spoofing' => 'USR-Spoofing',
- 'usr_start_time' => 'USR-Start-Time',
- 'usr_supports_tags' => 'USR-Supports-Tags',
- 'usr_sync_async_mode' => 'USR-Sync-Async-Mode',
- 'usr_syslog_tap' => 'USR-Syslog-Tap',
- 'usr_terminal_type' => 'USR-Terminal-Type',
- 'usr_transmit_acc_map' => 'USR-Transmit-Acc-Map',
- 'usr_tunnel_auth_hostname' => 'USR-Tunnel-Auth-Hostname',
- 'usr_tunnel_security' => 'USR-Tunnel-Security',
- 'usr_tunnel_switch_endpoi' => 'USR-Tunnel-Switch-Endpoint',
- 'usr_tunneled_mlpp' => 'USR-Tunneled-MLPP',
- 'usr_unauthenticated_time' => 'USR-Unauthenticated-Time',
- 'usr_vpn_encrypter' => 'USR-VPN-Encrypter',
- 'usr_vpn_gw_location_id' => 'USR-VPN-GW-Location-Id',
- 'usr_vts_session_key' => 'USR-VTS-Session-Key',
- 'vendor_specific' => 'Vendor-Specific',
- 'versanet_termination_cau' => 'Versanet-Termination-Cause',
- 'vnc_pppoe_cbq_rx' => 'VNC-PPPoE-CBQ-RX',
- 'vnc_pppoe_cbq_rx_fallbac' => 'VNC-PPPoE-CBQ-RX-Fallback',
- 'vnc_pppoe_cbq_tx' => 'VNC-PPPoE-CBQ-TX',
- 'vnc_pppoe_cbq_tx_fallbac' => 'VNC-PPPoE-CBQ-TX-Fallback',
- 'vnc_splash' => 'VNC-Splash',
- 'wispr_bandwidth_max_down' => 'WISPr-Bandwidth-Max-Down',
- 'wispr_bandwidth_max_up' => 'WISPr-Bandwidth-Max-Up',
- 'wispr_bandwidth_min_down' => 'WISPr-Bandwidth-Min-Down',
- 'wispr_bandwidth_min_up' => 'WISPr-Bandwidth-Min-Up',
- 'wispr_billing_class_of_s' => 'WISPr-Billing-Class-Of-Service',
- 'wispr_location_id' => 'WISPr-Location-ID',
- 'wispr_location_name' => 'WISPr-Location-Name',
- 'wispr_logoff_url' => 'WISPr-Logoff-URL',
- 'wispr_redirection_url' => 'WISPr-Redirection-URL',
- 'wispr_session_terminate_' => 'WISPr-Session-Terminate-Time',
- 'wispr_session_terminatea' => 'WISPr-Session-Terminate-End-Of-Day',
- 'x_ascend_add_seconds' => 'X-Ascend-Add-Seconds',
- 'x_ascend_ara_pw' => 'X-Ascend-Ara-PW',
- 'x_ascend_assign_ip_clien' => 'X-Ascend-Assign-IP-Client',
- 'x_ascend_assign_ip_globa' => 'X-Ascend-Assign-IP-Global-Pool',
- 'x_ascend_assign_ip_pool' => 'X-Ascend-Assign-IP-Pool',
- 'x_ascend_assign_ip_serve' => 'X-Ascend-Assign-IP-Server',
- 'x_ascend_authen_alias' => 'X-Ascend-Authen-Alias',
- 'x_ascend_backup' => 'X-Ascend-Backup',
- 'x_ascend_bacp_enable' => 'X-Ascend-BACP-Enable',
+ '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',
+ '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',
+ 'ascend_ppp_address' => 'Ascend-PPP-Address',
+ 'erx_maximum_bps' => 'ERX-Maximum-BPS',
+ 'caller_id' => 'Caller-ID',
+ 'bintec_ipfiltertable' => 'BinTec-ipFilterTable',
'x_ascend_base_channel_co' => 'X-Ascend-Base-Channel-Count',
- 'x_ascend_billing_number' => 'X-Ascend-Billing-Number',
- 'x_ascend_bridge' => 'X-Ascend-Bridge',
- 'x_ascend_bridge_address' => 'X-Ascend-Bridge-Address',
- 'x_ascend_call_attempt_li' => 'X-Ascend-Call-Attempt-Limit',
- 'x_ascend_call_block_dura' => 'X-Ascend-Call-Block-Duration',
- 'x_ascend_call_by_call' => 'X-Ascend-Call-By-Call',
- 'x_ascend_call_filter' => 'X-Ascend-Call-Filter',
- 'x_ascend_call_type' => 'X-Ascend-Call-Type',
- 'x_ascend_callback' => 'X-Ascend-Callback',
- 'x_ascend_client_assign_d' => 'X-Ascend-Client-Assign-DNS',
- 'x_ascend_client_gateway' => 'X-Ascend-Client-Gateway',
+ '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',
+ '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',
+ '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_receive_speed' => 'Annex-Receive-Speed',
+ 'usr_mobileip_home_agent_' => 'USR-MobileIP-Home-Agent-Address',
+ 'bind_l2tp_flow_control' => 'Bind-L2TP-Flow-Control',
+ 'smb_account_ctrl' => 'SMB-Account-CTRL',
+ 'ascend_ip_pool_chaining' => 'Ascend-IP-Pool-Chaining',
+ 'le_admin_group' => 'LE-Admin-Group',
+ 'tunnel_connection_id' => 'Tunnel-Connection-Id',
+ '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_pw_index' => 'USR-PW_Index',
+ 'erx_primary_wins' => 'ERX-Primary-Wins',
+ 'ascend_appletalk_peer_mo' => 'Ascend-Appletalk-Peer-Mode',
+ 'le_ipsec_log_options' => 'LE-IPSec-Log-Options',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'acc_nbns_server_sec' => 'Acc-Nbns-Server-Sec',
+ 'ms_chap_challenge' => 'MS-CHAP-Challenge',
+ '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',
+ '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',
+ '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',
+ 'bintec_ipxstaticroutetab' => 'BinTec-ipxStaticRouteTable',
+ 'ascend_dialout_allowed' => 'Ascend-Dialout-Allowed',
+ 'annex_local_username' => 'Annex-Local-Username',
+ 'cisco_pre_input_packets' => 'Cisco-Pre-Input-Packets',
+ 'shiva_function' => 'Shiva-Function',
+ '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',
'x_ascend_connect_progres' => 'X-Ascend-Connect-Progress',
- 'x_ascend_data_filter' => 'X-Ascend-Data-Filter',
- 'x_ascend_data_rate' => 'X-Ascend-Data-Rate',
- 'x_ascend_data_svc' => 'X-Ascend-Data-Svc',
- 'x_ascend_dba_monitor' => 'X-Ascend-DBA-Monitor',
- 'x_ascend_dec_channel_cou' => 'X-Ascend-Dec-Channel-Count',
- 'x_ascend_dhcp_maximum_le' => 'X-Ascend-DHCP-Maximum-Leases',
- 'x_ascend_dhcp_pool_numbe' => 'X-Ascend-DHCP-Pool-Number',
- 'x_ascend_dhcp_reply' => 'X-Ascend-DHCP-Reply',
- 'x_ascend_dial_number' => 'X-Ascend-Dial-Number',
- 'x_ascend_dialout_allowed' => 'X-Ascend-Dialout-Allowed',
- 'x_ascend_disconnect_caus' => 'X-Ascend-Disconnect-Cause',
- 'x_ascend_event_type' => 'X-Ascend-Event-Type',
+ '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',
+ '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',
+ 'nokia_ggsn_ip_address' => 'Nokia-GGSN-IP-Address',
+ 'acc_access_community' => 'Acc-Access-Community',
+ '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',
+ 'ascend_fr_direct_dlci' => 'Ascend-FR-Direct-DLCI',
+ 'ascend_qos_upstream' => 'Ascend-QOS-Upstream',
+ '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_fcp_parameter' => 'X-Ascend-FCP-Parameter',
- 'x_ascend_first_dest' => 'X-Ascend-First-Dest',
- 'x_ascend_force_56' => 'X-Ascend-Force-56',
- 'x_ascend_fr_circuit_name' => 'X-Ascend-FR-Circuit-Name',
- 'x_ascend_fr_dce_n392' => 'X-Ascend-FR-DCE-N392',
- 'x_ascend_fr_dce_n393' => 'X-Ascend-FR-DCE-N393',
- 'x_ascend_fr_direct' => 'X-Ascend-FR-Direct',
- 'x_ascend_fr_direct_dlci' => 'X-Ascend-FR-Direct-DLCI',
- 'x_ascend_fr_direct_profi' => 'X-Ascend-FR-Direct-Profile',
- 'x_ascend_fr_dlci' => 'X-Ascend-FR-DLCI',
- 'x_ascend_fr_dte_n392' => 'X-Ascend-FR-DTE-N392',
- 'x_ascend_fr_dte_n393' => 'X-Ascend-FR-DTE-N393',
- 'x_ascend_fr_link_mgt' => 'X-Ascend-FR-Link-Mgt',
- 'x_ascend_fr_linkup' => 'X-Ascend-FR-LinkUp',
- 'x_ascend_fr_n391' => 'X-Ascend-FR-N391',
- 'x_ascend_fr_nailed_grp' => 'X-Ascend-FR-Nailed-Grp',
- 'x_ascend_fr_profile_name' => 'X-Ascend-FR-Profile-Name',
- 'x_ascend_fr_t391' => 'X-Ascend-FR-T391',
- 'x_ascend_fr_t392' => 'X-Ascend-FR-T392',
- 'x_ascend_fr_type' => 'X-Ascend-FR-Type',
- 'x_ascend_ft1_caller' => 'X-Ascend-FT1-Caller',
- 'x_ascend_group' => 'X-Ascend-Group',
- 'x_ascend_handle_ipx' => 'X-Ascend-Handle-IPX',
- 'x_ascend_history_weigh_t' => 'X-Ascend-History-Weigh-Type',
+ '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',
'x_ascend_home_agent_ip_a' => 'X-Ascend-Home-Agent-IP-Addr',
- 'x_ascend_home_agent_pass' => 'X-Ascend-Home-Agent-Password',
+ 'usr_disconnect_cause_ind' => 'USR-Disconnect-Cause-Indicator',
+ 'bg_span_dis' => 'BG-Span-Dis',
+ 'cisco_multilink_id' => 'Cisco-Multilink-ID',
+ 'tunnel_max_tunnels' => 'Tunnel-Max-Tunnels',
+ 'ascend_dsl_downstream_li' => 'Ascend-Dsl-Downstream-Limit',
+ 'ascend_multilink_id' => 'Ascend-Multilink-ID',
+ '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',
+ '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',
'x_ascend_home_agent_udp_' => 'X-Ascend-Home-Agent-UDP-Port',
- 'x_ascend_home_network_na' => 'X-Ascend-Home-Network-Name',
- 'x_ascend_host_info' => 'X-Ascend-Host-Info',
- 'x_ascend_idle_limit' => 'X-Ascend-Idle-Limit',
- 'x_ascend_if_netmask' => 'X-Ascend-IF-Netmask',
- 'x_ascend_inc_channel_cou' => 'X-Ascend-Inc-Channel-Count',
- 'x_ascend_ip_direct' => 'X-Ascend-IP-Direct',
+ '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',
+ 'cvpn3000_reqrd_client_fx' => 'CVPN3000-Reqrd-Client-Fw-Product-Code',
+ 'bg_path_cost' => 'BG-Path-Cost',
+ 'usr_modem_training_time' => 'USR-Modem-Training-Time',
+ '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',
+ 'usr_appletalk' => 'USR-Appletalk',
+ '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',
+ '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',
+ 'cvpn3000_ipsec_backup_se' => 'CVPN3000-IPSec-Backup-Servers',
+ 'termination_action' => 'Termination-Action',
+ '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',
+ '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',
+ 'usr_pw_vpn_name' => 'USR-PW_VPN_Name',
+ 'nomadix_ip_upsell' => 'Nomadix-IP-Upsell',
+ 'ascend_nas_port_format' => 'Ascend-NAS-Port-Format',
+ 'usr_dtr_true_timeout' => 'USR-DTR-True-Timeout',
+ 'shasta_vpn_name' => 'Shasta-VPN-Name',
+ 'connect_rate' => 'Connect-Rate',
+ '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',
+ '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',
+ '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',
+ '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',
+ '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',
+ 'erx_sa_validate' => 'ERX-Sa-Validate',
+ 'ascend_service_type' => 'Ascend-Service-Type',
+ 'usr_pw_vpn_gateway' => 'USR-PW_VPN_Gateway',
+ 'acc_ip_compression' => 'Acc-Ip-Compression',
+ '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',
+ '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',
+ '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',
- 'x_ascend_ipx_alias' => 'X-Ascend-IPX-Alias',
- 'x_ascend_ipx_node_addr' => 'X-Ascend-IPX-Node-Addr',
- 'x_ascend_ipx_peer_mode' => 'X-Ascend-IPX-Peer-Mode',
- 'x_ascend_ipx_route' => 'X-Ascend-IPX-Route',
- 'x_ascend_link_compressio' => 'X-Ascend-Link-Compression',
- 'x_ascend_maximum_call_du' => 'X-Ascend-Maximum-Call-Duration',
- 'x_ascend_maximum_channel' => 'X-Ascend-Maximum-Channels',
- 'x_ascend_maximum_time' => 'X-Ascend-Maximum-Time',
- 'x_ascend_menu_item' => 'X-Ascend-Menu-Item',
- 'x_ascend_menu_selector' => 'X-Ascend-Menu-Selector',
- 'x_ascend_metric' => 'X-Ascend-Metric',
+ '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',
+ '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',
+ 'current_time' => 'Current-Time',
+ 'cisco_xmit_rate' => 'Cisco-Xmit-Rate',
+ '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',
- 'x_ascend_modem_portno' => 'X-Ascend-Modem-PortNo',
- 'x_ascend_modem_shelfno' => 'X-Ascend-Modem-ShelfNo',
- 'x_ascend_modem_slotno' => 'X-Ascend-Modem-SlotNo',
- 'x_ascend_mpp_idle_percen' => 'X-Ascend-MPP-Idle-Percent',
- 'x_ascend_multicast_clien' => 'X-Ascend-Multicast-Client',
- 'x_ascend_multicast_rate_' => 'X-Ascend-Multicast-Rate-Limit',
- 'x_ascend_multilink_id' => 'X-Ascend-Multilink-ID',
- 'x_ascend_netware_timeout' => 'X-Ascend-Netware-timeout',
- 'x_ascend_num_in_multilin' => 'X-Ascend-Num-In-Multilink',
- 'x_ascend_number_sessions' => 'X-Ascend-Number-Sessions',
- 'x_ascend_ppp_address' => 'X-Ascend-PPP-Address',
- 'x_ascend_ppp_async_map' => 'X-Ascend-PPP-Async-Map',
- 'x_ascend_ppp_vj_1172' => 'X-Ascend-PPP-VJ-1172',
- 'x_ascend_ppp_vj_slot_com' => 'X-Ascend-PPP-VJ-Slot-Comp',
- 'x_ascend_pre_input_octet' => 'X-Ascend-Pre-Input-Octets',
- 'x_ascend_pre_input_packe' => 'X-Ascend-Pre-Input-Packets',
- 'x_ascend_pre_output_octe' => 'X-Ascend-Pre-Output-Octets',
- 'x_ascend_pre_output_pack' => 'X-Ascend-Pre-Output-Packets',
- 'x_ascend_preempt_limit' => 'X-Ascend-Preempt-Limit',
- 'x_ascend_presession_time' => 'X-Ascend-PreSession-Time',
+ 'usr_event_date_time' => 'USR-Event-Date-Time',
+ 'x_ascend_ipx_node_addr' => 'X-Ascend-IPX-Node-Addr',
+ 'cvpn3000_ipsec_over_udp' => 'CVPN3000-IPSec-Over-UDP',
+ 'x_ascend_user_acct_time' => 'X-Ascend-User-Acct-Time',
+ 'cisco_email_server_ack_f' => 'Cisco-Email-Server-Ack-Flag',
+ 'telebit_activate_command' => 'Telebit-Activate-Command',
+ 'acc_output_errors' => 'Acc-Output-Errors',
+ 'juniper_allow_configurat' => 'Juniper-Allow-Configuration',
+ 'bind_l2tp_tunnel_name' => 'Bind-L2TP-Tunnel-Name',
'x_ascend_pri_number_type' => 'X-Ascend-PRI-Number-Type',
- 'x_ascend_primary_home_ag' => 'X-Ascend-Primary-Home-Agent',
- 'x_ascend_pw_lifetime' => 'X-Ascend-PW-Lifetime',
- 'x_ascend_pw_warntime' => 'X-Ascend-PW-Warntime',
- 'x_ascend_receive_secret' => 'X-Ascend-Receive-Secret',
- 'x_ascend_remote_addr' => 'X-Ascend-Remote-Addr',
- 'x_ascend_remove_seconds' => 'X-Ascend-Remove-Seconds',
- 'x_ascend_require_auth' => 'X-Ascend-Require-Auth',
- 'x_ascend_route_ip' => 'X-Ascend-Route-IP',
- 'x_ascend_route_ipx' => 'X-Ascend-Route-IPX',
- 'x_ascend_secondary_home_' => 'X-Ascend-Secondary-Home-Agent',
- 'x_ascend_seconds_of_hist' => 'X-Ascend-Seconds-Of-History',
- 'x_ascend_send_auth' => 'X-Ascend-Send-Auth',
- 'x_ascend_send_passwd' => 'X-Ascend-Send-Passwd',
- 'x_ascend_send_secret' => 'X-Ascend-Send-Secret',
- 'x_ascend_session_svr_key' => 'X-Ascend-Session-Svr-Key',
- 'x_ascend_shared_profile_' => 'X-Ascend-Shared-Profile-Enable',
- 'x_ascend_target_util' => 'X-Ascend-Target-Util',
- 'x_ascend_temporary_rtes' => 'X-Ascend-Temporary-Rtes',
- 'x_ascend_third_prompt' => 'X-Ascend-Third-Prompt',
- 'x_ascend_token_expiry' => 'X-Ascend-Token-Expiry',
- 'x_ascend_token_idle' => 'X-Ascend-Token-Idle',
- 'x_ascend_token_immediate' => 'X-Ascend-Token-Immediate',
- 'x_ascend_transit_number' => 'X-Ascend-Transit-Number',
- 'x_ascend_ts_idle_limit' => 'X-Ascend-TS-Idle-Limit',
- 'x_ascend_ts_idle_mode' => 'X-Ascend-TS-Idle-Mode',
- 'x_ascend_tunneling_proto' => 'X-Ascend-Tunneling-Protocol',
- 'x_ascend_user_acct_base' => 'X-Ascend-User-Acct-Base',
- 'x_ascend_user_acct_host' => 'X-Ascend-User-Acct-Host',
- 'x_ascend_user_acct_key' => 'X-Ascend-User-Acct-Key',
- 'x_ascend_user_acct_port' => 'X-Ascend-User-Acct-Port',
- 'x_ascend_user_acct_time' => 'X-Ascend-User-Acct-Time',
- 'x_ascend_user_acct_type' => 'X-Ascend-User-Acct-Type',
- 'x_ascend_xmit_rate' => 'X-Ascend-Xmit-Rate',
- 'xedia_address_pool' => 'Xedia-Address-Pool',
- 'xedia_client_access_netw' => 'Xedia-Client-Access-Network',
- 'xedia_dns_server' => 'Xedia-DNS-Server',
- 'xedia_netbios_server' => 'Xedia-NetBios-Server',
- 'xedia_ppp_echo_interval' => 'Xedia-PPP-Echo-Interval',
- 'xedia_ssh_privileges' => 'Xedia-SSH-Privileges',
+ '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',
+ 'usr_et_bridge_call_outpu' => 'USR-ET-Bridge-Call-Output-Filte',
+ 'usr_secondary_dns_server' => 'USR-Secondary_DNS_Server',
+ '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',
+ 'cvpn5000_client_real_ip' => 'CVPN5000-Client-Real-IP',
+ 'usr_rmmie_status' => 'USR-RMMIE-Status',
+ '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',
+ 'usr_at_input_filter' => 'USR-AT-Input-Filter',
+ 'usr_auth_mode' => 'USR-Auth-Mode',
+ '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',
+ 'bind_tun_contexu' => 'Bind_Tun_Context',
+ 'usr_pw_usr_ofilter_ipx' => 'USR-PW_USR_OFilter_IPX',
+ 'framed_routing' => 'Framed-Routing',
+ 'annex_primary_nbns_serve' => 'Annex-Primary-NBNS-Server',
+ 'usr_interface_index' => 'USR-Interface-Index',
+ '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',
+ 'tunnel_retransmit' => 'Tunnel-Retransmit',
+ 'acct_tunnel_connection' => 'Acct-Tunnel-Connection',
+ 'x_ascend_backup' => 'X-Ascend-Backup',
+ 'xedia_ppp_echo_interval' => 'Xedia-PPP-Echo-Interval',
+ 'usr_bearer_capabilities' => 'USR-Bearer-Capabilities',
+ 'shiva_acct_serv_switch' => 'Shiva-Acct-Serv-Switch',
+ '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',
+ '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',
+ 'cisco_email_server_addre' => 'Cisco-Email-Server-Address',
+ 'ascend_x25_x121_address' => 'Ascend-X25-X121-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',
+ 'exec_program_wait' => 'Exec-Program-Wait',
+ 'framed_interface_id' => 'Framed-Interface-Id',
#NETC.NET.AU (RADIATOR?)
- 'authentication_type' => 'Authentication-Type',
-
- #wtxs (dunno)
- #'radius_operator' => 'Radius-Operator',
+ 'authentication_type' => 'Authentication-Type',
);
diff --git a/FS/FS/rate.pm b/FS/FS/rate.pm
index a471e2ea4..b8a694041 100644
--- a/FS/FS/rate.pm
+++ b/FS/FS/rate.pm
@@ -1,14 +1,12 @@
package FS::rate;
use strict;
-use vars qw( @ISA $DEBUG );
-use FS::Record qw( qsearch qsearchs dbh fields );
+use vars qw( @ISA );
+use FS::Record qw( qsearch qsearchs dbh );
use FS::rate_detail;
@ISA = qw(FS::Record);
-$DEBUG = 1;
-
=head1 NAME
FS::rate - Object methods for rate records
@@ -96,32 +94,13 @@ sub insert {
}
if ( $options{'rate_detail'} ) {
-
- my( $num, $last, $min_sec ) = (0, time, 5); #progressbar foo
-
foreach my $rate_detail ( @{$options{'rate_detail'}} ) {
-
$rate_detail->ratenum($self->ratenum);
$error = $rate_detail->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
-
- if ( $options{'job'} ) {
- $num++;
- if ( time - $min_sec > $last ) {
- my $error = $options{'job'}->update_statustext(
- int( 100 * $num / scalar( @{$options{'rate_detail'}} ) )
- );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- $last = time;
- }
- }
-
}
}
@@ -169,8 +148,8 @@ sub replace {
local $FS::UID::AutoCommit = 0;
my $dbh = dbh;
-# my @old_rate_detail = ();
-# @old_rate_detail = $old->rate_detail if $options{'rate_detail'};
+ my @old_rate_detail = ();
+ @old_rate_detail = $old->rate_detail if $options{'rate_detail'};
my $error = $new->SUPER::replace($old);
if ($error) {
@@ -178,67 +157,21 @@ sub replace {
return $error;
}
-# foreach my $old_rate_detail ( @old_rate_detail ) {
-#
-# my $error = $old_rate_detail->delete;
-# if ($error) {
-# $dbh->rollback if $oldAutoCommit;
-# return $error;
-# }
-#
-# if ( $options{'job'} ) {
-# $num++;
-# if ( time - $min_sec > $last ) {
-# my $error = $options{'job'}->update_statustext(
-# int( 50 * $num / scalar( @old_rate_detail ) )
-# );
-# if ( $error ) {
-# $dbh->rollback if $oldAutoCommit;
-# return $error;
-# }
-# $last = time;
-# }
-# }
-#
-# }
- if ( $options{'rate_detail'} ) {
- my $sth = $dbh->prepare('DELETE FROM rate_detail WHERE ratenum = ?') or do {
- $dbh->rollback if $oldAutoCommit;
- return $dbh->errstr;
- };
-
- $sth->execute($old->ratenum) or do {
+ foreach my $old_rate_detail ( @old_rate_detail ) {
+ my $error = $old_rate_detail->delete;
+ if ($error) {
$dbh->rollback if $oldAutoCommit;
- return $sth->errstr;
- };
-
- my( $num, $last, $min_sec ) = (0, time, 5); #progresbar foo
-# $num = 0;
- foreach my $rate_detail ( @{$options{'rate_detail'}} ) {
-
- $rate_detail->ratenum($new->ratenum);
- $error = $rate_detail->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- if ( $options{'job'} ) {
- $num++;
- if ( time - $min_sec > $last ) {
- my $error = $options{'job'}->update_statustext(
- int( 100 * $num / scalar( @{$options{'rate_detail'}} ) )
- );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- $last = time;
- }
- }
-
+ return $error;
}
+ }
+ foreach my $rate_detail ( @{$options{'rate_detail'}} ) {
+ $rate_detail->ratenum($new->ratenum);
+ $error = $rate_detail->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
@@ -297,76 +230,6 @@ sub rate_detail {
=back
-=head1 SUBROUTINES
-
-=over 4
-
-=item process
-
-Experimental job-queue processor for web interface adds/edits
-
-=cut
-
-use Storable qw(thaw);
-use Data::Dumper;
-use MIME::Base64;
-sub process {
- my $job = shift;
-
- my $param = thaw(decode_base64(shift));
- warn Dumper($param) if $DEBUG;
-
- my $old = qsearchs('rate', { 'ratenum' => $param->{'ratenum'} } )
- if $param->{'ratenum'};
-
- my @rate_detail = map {
-
- my $regionnum = $_->regionnum;
- if ( $param->{"sec_granularity$regionnum"} ) {
-
- new FS::rate_detail {
- 'dest_regionnum' => $regionnum,
- map { $_ => $param->{"$_$regionnum"} }
- qw( min_included min_charge sec_granularity )
- };
-
- } else {
-
- new FS::rate_detail {
- 'dest_regionnum' => $regionnum,
- 'min_included' => 0,
- 'min_charge' => 0,
- 'sec_granularity' => '60'
- };
-
- }
-
- } qsearch('rate_region', {} );
-
- my $rate = new FS::rate {
- map { $_ => $param->{$_} }
- fields('rate')
- };
-
- my $error = '';
- if ( $param->{'ratenum'} ) {
- warn "$rate replacing $old (". $param->{'ratenum'}. ")\n" if $DEBUG;
- $error = $rate->replace( $old,
- 'rate_detail' => \@rate_detail,
- 'job' => $job,
- );
- } else {
- warn "inserting $rate\n" if $DEBUG;
- $error = $rate->insert( 'rate_detail' => \@rate_detail,
- 'job' => $job,
- );
- #$ratenum = $rate->getfield('ratenum');
- }
-
- die "$error\n" if $error;
-
-}
-
=head1 BUGS
=head1 SEE ALSO
diff --git a/FS/FS/rate_detail.pm b/FS/FS/rate_detail.pm
index 7d54355fb..313b0533d 100644
--- a/FS/FS/rate_detail.pm
+++ b/FS/FS/rate_detail.pm
@@ -34,8 +34,6 @@ inherits from FS::Record. The following fields are currently supported:
=over 4
-=item ratedetailnum - primary key
-
=item ratenum - rate plan (see L<FS::rate>)
=item orig_regionnum - call origination region
@@ -108,8 +106,7 @@ sub check {
my $self = shift;
my $error =
- $self->ut_numbern('ratedetailnum')
- || $self->ut_foreign_key('ratenum', 'rate', 'ratenum')
+ $self->ut_foreign_key('ratenum', 'rate', 'ratenum')
|| $self->ut_foreign_keyn('orig_regionnum', 'rate_region', 'regionnum' )
|| $self->ut_foreign_key('dest_regionnum', 'rate_region', 'regionnum' )
|| $self->ut_number('min_included')
diff --git a/FS/FS/rate_prefix.pm b/FS/FS/rate_prefix.pm
index 42b004f5b..500462a15 100644
--- a/FS/FS/rate_prefix.pm
+++ b/FS/FS/rate_prefix.pm
@@ -122,7 +122,7 @@ Returns the rate region (see L<FS::rate_region>) for this prefix.
sub rate_region {
my $self = shift;
- qsearchs('rate_region', { 'regionnum' => $self->regionnum } );
+ qsearch('rate_region', { 'regionnum' => $self->regionnum } );
}
=back
diff --git a/FS/FS/reg_code.pm b/FS/FS/reg_code.pm
deleted file mode 100644
index f48ccf048..000000000
--- a/FS/FS/reg_code.pm
+++ /dev/null
@@ -1,223 +0,0 @@
-package FS::reg_code;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw(qsearch dbh);
-use FS::agent;
-use FS::reg_code_pkg;
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::reg_code - One-time registration codes
-
-=head1 SYNOPSIS
-
- use FS::reg_code;
-
- $record = new FS::reg_code \%hash;
- $record = new FS::reg_code { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::reg_code object is a one-time registration code. FS::reg_code inherits
-from FS::Record. The following fields are currently supported:
-
-=over 4
-
-=item codenum - primary key
-
-=item code - registration code string
-
-=item agentnum - Agent (see L<FS::agent>)
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new registration code. To add the code 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'reg_code'; }
-
-=item insert [ PKGPART_ARRAYREF ]
-
-Adds this record to the database. If an arrayref of pkgparts
-(see L<FS::part_pkg>) is specified, the appropriate reg_code_pkg records
-(see L<FS::reg_code_pkg>) will be inserted.
-
-If there is an error, returns the error, otherwise returns false.
-
-=cut
-
-sub insert {
- 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;
-
- my $error = $self->SUPER::insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- if ( @_ ) {
- my $pkgparts = shift;
- foreach my $pkgpart ( @$pkgparts ) {
- my $reg_code_pkg = new FS::reg_code_pkg ( {
- 'codenum' => $self->codenum,
- 'pkgpart' => $pkgpart,
- } );
- $error = $reg_code_pkg->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-=item delete
-
-Delete this record (and all associated reg_code_pkg records) from the database.
-
-=cut
-
-sub delete {
- 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 $reg_code_pkg ( $self->reg_code_pkg ) {
- my $error = $reg_code_pkg->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- my $error = $self->SUPER::delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-=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 registration code. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('codenum')
- || $self->ut_alpha('code')
- || $self->ut_foreign_key('agentnum', 'agent', 'agentnum')
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=item part_pkg
-
-Returns all package definitions (see L<FS::part_pkg> for this registration
-code.
-
-=cut
-
-sub part_pkg {
- my $self = shift;
- map { $_->part_pkg } $self->reg_code_pkg;
-}
-
-=item reg_code_pkg
-
-Returns all FS::reg_code_pkg records for this registration code.
-
-=cut
-
-sub reg_code_pkg {
- my $self = shift;
- qsearch('reg_code_pkg', { 'codenum' => $self->codenum } );
-}
-
-
-=back
-
-=head1 BUGS
-
-Feeping creaturitis.
-
-=head1 SEE ALSO
-
-L<FS::reg_code_pkg>, L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
-
diff --git a/FS/FS/reg_code_pkg.pm b/FS/FS/reg_code_pkg.pm
deleted file mode 100644
index 9b9a87712..000000000
--- a/FS/FS/reg_code_pkg.pm
+++ /dev/null
@@ -1,138 +0,0 @@
-package FS::reg_code_pkg;
-
-use strict;
-use vars qw( @ISA );
-use FS::Record qw(qsearchs);
-use FS::reg_code;
-use FS::part_pkg;
-
-@ISA = qw(FS::Record);
-
-=head1 NAME
-
-FS::reg_code_pkg - Class linking registration codes (see L<FS::reg_code>) with package definitions (see L<FS::part_pkg>)
-
-=head1 SYNOPSIS
-
- use FS::reg_code_pkg;
-
- $record = new FS::reg_code_pkg \%hash;
- $record = new FS::reg_code_pkg { 'column' => 'value' };
-
- $error = $record->insert;
-
- $error = $new_record->replace($old_record);
-
- $error = $record->delete;
-
- $error = $record->check;
-
-=head1 DESCRIPTION
-
-An FS::reg_code_pkg object links a registration code to a package definition.
-FS::table_name inherits from FS::Record. The following fields are currently
-supported:
-
-=over 4
-
-=item codepkgnum - primary key
-
-=item codenum - registration code (see L<FS::reg_code>)
-
-=item pkgpart - package definition (see L<FS::part_pkg>)
-
-=back
-
-=head1 METHODS
-
-=over 4
-
-=item new HASHREF
-
-Creates a new example. To add the example 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
-
-# the new method can be inherited from FS::Record, if a table method is defined
-
-sub table { 'reg_code_pkg'; }
-
-=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 record. If there is
-an error, returns the error, otherwise returns false. Called by the insert
-and replace methods.
-
-=cut
-
-# the check method should currently be supplied - FS::Record contains some
-# data checking routines
-
-sub check {
- my $self = shift;
-
- my $error =
- $self->ut_numbern('codepkgnum')
- || $self->ut_foreign_key('codenum', 'reg_code', 'codenum')
- || $self->ut_foreign_key('pkgpart', 'part_pkg', 'pkgpart')
- ;
- return $error if $error;
-
- $self->SUPER::check;
-}
-
-=item part_pkg
-
-Returns the package definition (see L<FS::part_pkg>)
-
-=cut
-
-sub part_pkg {
- my $self = shift;
- qsearchs('part_pkg', { 'pkgpart' => $self->pkgpart } );
-}
-
-=back
-
-=head1 BUGS
-
-Feeping creaturitis.
-
-=head1 SEE ALSO
-
-L<FS::reg_code_pkg>, L<FS::Record>, schema.html from the base documentation.
-
-=cut
-
-1;
-
-
diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm
index 962e36a07..10ff3f916 100644
--- a/FS/FS/svc_Common.pm
+++ b/FS/FS/svc_Common.pm
@@ -2,17 +2,15 @@ package FS::svc_Common;
use strict;
use vars qw( @ISA $noexport_hack $DEBUG );
-use Carp;
use FS::Record qw( qsearch qsearchs fields dbh );
-use FS::cust_main_Mixin;
use FS::cust_svc;
use FS::part_svc;
use FS::queue;
-use FS::cust_main;
-@ISA = qw( FS::cust_main_Mixin FS::Record );
+@ISA = qw( FS::Record );
$DEBUG = 0;
+#$DEBUG = 1;
=head1 NAME
@@ -35,38 +33,6 @@ inherit from, i.e. FS::svc_acct. FS::svc_Common inherits from FS::Record.
=cut
-sub new {
- my $proto = shift;
- my $class = ref($proto) || $proto;
- my $self = {};
- bless ($self, $class);
-
- unless ( defined ( $self->table ) ) {
- $self->{'Table'} = shift;
- carp "warning: FS::Record::new called with table name ". $self->{'Table'};
- }
-
- #$self->{'Hash'} = shift;
- my $newhash = shift;
- $self->{'Hash'} = { map { $_ => $newhash->{$_} } qw(svcnum svcpart) };
- $self->setdefault;
- $self->{'Hash'}{$_} = $newhash->{$_}
- foreach grep { defined($newhash->{$_}) && length($newhash->{$_}) }
- keys %$newhash;
-
- foreach my $field ( grep !defined($self->{'Hash'}{$_}), $self->fields ) {
- $self->{'Hash'}{$field}='';
- }
-
- $self->_rebless if $self->can('_rebless');
-
- $self->{'modified'} = 0;
-
- $self->_cache($self->{'Hash'}, shift) if $self->can('_cache') && @_;
-
- $self;
-}
-
sub virtual_fields {
# This restricts the fields based on part_svc_column and the svcpart of
@@ -134,11 +100,8 @@ If I<jobnum> is set to an array reference, the jobnums of any export jobs will
be added to the referenced array.
If I<child_objects> is set to an array reference of FS::tablename objects (for
-example, FS::acct_snarf objects), they will have their svcnum field set and
-will be inserted after this record, but before any exports are run. Each
-element of the array can also optionally be a two-element array reference
-containing the child object and the name of an alternate field to be filled in
-with the newly-inserted svcnum, for example C<[ $svc_forward, 'srcsvc' ]>
+example, FS::acct_snarf objects), they will have their svcnum fieldsset and
+will be inserted after this record, but before any exports are run.
If I<depend_jobnum> is set (to a scalar jobnum or an array reference of
jobnums), all provisioning jobs will have a dependancy on the supplied
@@ -209,15 +172,8 @@ sub insert {
}
foreach my $object ( @$objects ) {
- my($field, $obj);
- if ( ref($object) eq 'ARRAY' ) {
- ($obj, $field) = @$object;
- } else {
- $obj = $object;
- $field = 'svcnum';
- }
- $obj->$field($self->svcnum);
- $error = $obj->insert;
+ $object->svcnum($self->svcnum);
+ $error = $object->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm
index c1851d3ce..8e47abfc5 100644
--- a/FS/FS/svc_acct.pm
+++ b/FS/FS/svc_acct.pm
@@ -1,12 +1,12 @@
package FS::svc_acct;
use strict;
-use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
+use vars qw( @ISA $DEBUG $me $conf
$dir_prefix @shells $usernamemin
$usernamemax $passwordmin $passwordmax
$username_ampersand $username_letter $username_letterfirst
$username_noperiod $username_nounderscore $username_nodash
- $username_uppercase $username_percent
+ $username_uppercase
$password_noampersand $password_noexclamation
$welcome_template $welcome_from $welcome_subject $welcome_mimetype
$smtpmachine
@@ -15,8 +15,7 @@ use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
@saltset @pw_set );
use Carp;
use Fcntl qw(:flock);
-use Date::Format;
-use Crypt::PasswdMD5 1.2;
+use Crypt::PasswdMD5;
use FS::UID qw( datasrc );
use FS::Conf;
use FS::Record qw( qsearch qsearchs fields dbh dbdef );
@@ -38,6 +37,7 @@ use FS::svc_www;
@ISA = qw( FS::svc_Common );
$DEBUG = 0;
+#$DEBUG = 1;
$me = '[FS::svc_acct]';
#ask FS::UID to run this stuff for us later
@@ -56,7 +56,6 @@ $FS::UID::callback{'FS::svc_acct'} = sub {
$username_nodash = $conf->exists('username-nodash');
$username_uppercase = $conf->exists('username-uppercase');
$username_ampersand = $conf->exists('username-ampersand');
- $username_percent = $conf->exists('username-percent');
$password_noampersand = $conf->exists('password-noexclamation');
$password_noexclamation = $conf->exists('password-noexclamation');
$dirhash = $conf->config('dirhash') || 0;
@@ -168,9 +167,7 @@ FS::svc_Common. The following fields are currently supported:
=item domsvc - svcnum from svc_domain
-=item radius_I<Radius_Attribute> - I<Radius-Attribute> (reply)
-
-=item rc_I<Radius_Attribute> - I<Radius-Attribute> (check)
+=item radius_I<Radius_Attribute> - I<Radius-Attribute>
=back
@@ -200,10 +197,7 @@ contain an arrayref of group names. See L<FS::radius_usergroup>.
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. Each element of the array can also optionally be a
-two-element array reference containing the child object and the name of an
-alternate field to be filled in with the newly-inserted svcnum, for example
-C<[ $svc_forward, 'srcsvc' ]>
+exports are run.
Currently available options are: I<depend_jobnum>
@@ -277,12 +271,15 @@ sub insert {
}
}
- unless ( $skip_fuzzyfiles ) {
- $error = $self->queue_fuzzyfiles_update;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "updating fuzzy search cache: $error";
- }
+ #false laziness with sub replace (and cust_main)
+ my $queue = new FS::queue {
+ 'svcnum' => $self->svcnum,
+ 'job' => 'FS::svc_acct::append_fuzzyfiles'
+ };
+ $error = $queue->insert($self->username);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "queueing job (transaction rolled back): $error";
}
my $cust_pkg = $self->cust_svc->cust_pkg;
@@ -299,7 +296,7 @@ sub insert {
#welcome email
my $to = '';
if ( $welcome_template && $cust_pkg ) {
- my $to = join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list );
+ my $to = join(', ', grep { $_ ne 'POST' } $cust_main->invoicing_list );
if ( $to ) {
my $wqueue = new FS::queue {
'svcnum' => $self->svcnum,
@@ -464,18 +461,15 @@ sub replace {
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,
+ 'domsvc' => $new->domsvc,
+ } );
{
#no warnings 'numeric'; #alas, a 5.006-ism
local($^W) = 0;
-
- foreach my $xid (qw( uid gid )) {
-
- return "Can't change $xid!"
- if ! $conf->exists("svc_acct-edit_$xid")
- && $old->$xid() != $new->$xid()
- && $new->cust_svc->part_svc->part_svc_column($xid)->columnflag ne 'F'
- }
-
+ return "Can't change uid!" if $old->uid != $new->uid;
}
#change homdir when we change username
@@ -497,10 +491,8 @@ sub replace {
return $error if $error;
$old->usergroup( [ $old->radius_groups ] );
- if ( $DEBUG ) {
- warn $old->email. " old groups: ". join(' ',@{$old->usergroup}). "\n";
- warn $new->email. "new groups: ". join(' ',@{$new->usergroup}). "\n";
- }
+ warn "old groups: ". join(' ',@{$old->usergroup}). "\n" if $DEBUG;
+ warn "new groups: ". join(' ',@{$new->usergroup}). "\n" if $DEBUG;
if ( $new->usergroup ) {
#(sorta) false laziness with FS::part_export::sqlradius::_export_replace
my @newgroups = @{$new->usergroup};
@@ -549,11 +541,16 @@ sub replace {
return $error if $error;
}
- if ( $new->username ne $old->username && ! $skip_fuzzyfiles ) {
- $error = $new->queue_fuzzyfiles_update;
+ if ( $new->username ne $old->username ) {
+ #false laziness with sub insert (and cust_main)
+ my $queue = new FS::queue {
+ 'svcnum' => $new->svcnum,
+ 'job' => 'FS::svc_acct::append_fuzzyfiles'
+ };
+ $error = $queue->insert($new->username);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return "updating fuzzy search cache: $error";
+ return "queueing job (transaction rolled back): $error";
}
}
@@ -561,42 +558,6 @@ sub replace {
''; #no error
}
-=item queue_fuzzyfiles_update
-
-Used by insert & replace to update the fuzzy search cache
-
-=cut
-
-sub queue_fuzzyfiles_update {
- 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;
-
- my $queue = new FS::queue {
- 'svcnum' => $self->svcnum,
- 'job' => 'FS::svc_acct::append_fuzzyfiles'
- };
- my $error = $queue->insert($self->username);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "queueing job (transaction rolled back): $error";
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-
=item suspend
Suspends this account by calling export-specific suspend hooks. If there is
@@ -699,11 +660,11 @@ sub check {
my $ulen = $usernamemax || $self->dbdef_table->column('username')->length;
if ( $username_uppercase ) {
- $recref->{username} =~ /^([a-z0-9_\-\.\&\%]{$usernamemin,$ulen})$/i
+ $recref->{username} =~ /^([a-z0-9_\-\.\&]{$usernamemin,$ulen})$/i
or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
$recref->{username} = $1;
} else {
- $recref->{username} =~ /^([a-z0-9_\-\.\&\%]{$usernamemin,$ulen})$/
+ $recref->{username} =~ /^([a-z0-9_\-\.\&]{$usernamemin,$ulen})$/
or return gettext('illegal_username'). " ($usernamemin-$ulen): ". $recref->{username};
$recref->{username} = $1;
}
@@ -731,9 +692,6 @@ sub check {
if ( $password_noexclamation ) {
$recref->{_password} =~ /\!/ and return gettext('illegal_password');
}
- unless ( $username_percent ) {
- $recref->{username} =~ /\%/ and return gettext('illegal_username');
- }
$recref->{popnum} =~ /^(\d*)$/ or return "Illegal popnum: ".$recref->{popnum};
$recref->{popnum} = $1;
@@ -755,28 +713,6 @@ sub check {
if $recref->{uid} == 0
&& $recref->{username} !~ /^(root|toor|smtp)$/;
- unless ( $recref->{username} eq 'sync' ) {
- if ( grep $_ eq $recref->{shell}, @shells ) {
- $recref->{shell} = (grep $_ eq $recref->{shell}, @shells)[0];
- } else {
- return "Illegal shell \`". $self->shell. "\'; ".
- $conf->dir. "/shells contains: @shells";
- }
- } else {
- $recref->{shell} = '/bin/sync';
- }
-
- } else {
- $recref->{gid} ne '' ?
- return "Can't have gid without uid" : ( $recref->{gid}='' );
- #$recref->{dir} ne '' ?
- # return "Can't have directory without uid" : ( $recref->{dir}='' );
- $recref->{shell} ne '' ?
- return "Can't have shell without uid" : ( $recref->{shell}='' );
- }
-
- unless ( $part_svc->part_svc_column('dir')->columnflag eq 'F' ) {
-
$recref->{dir} =~ /^([\/\w\-\.\&]*)$/
or return "Illegal directory: ". $recref->{dir};
$recref->{dir} = $1;
@@ -799,6 +735,24 @@ sub check {
;
}
+ unless ( $recref->{username} eq 'sync' ) {
+ if ( grep $_ eq $recref->{shell}, @shells ) {
+ $recref->{shell} = (grep $_ eq $recref->{shell}, @shells)[0];
+ } else {
+ return "Illegal shell \`". $self->shell. "\'; ".
+ $conf->dir. "/shells contains: @shells";
+ }
+ } else {
+ $recref->{shell} = '/bin/sync';
+ }
+
+ } else {
+ $recref->{gid} ne '' ?
+ return "Can't have gid without uid" : ( $recref->{gid}='' );
+ $recref->{dir} ne '' ?
+ return "Can't have directory without uid" : ( $recref->{dir}='' );
+ $recref->{shell} ne '' ?
+ return "Can't have shell without uid" : ( $recref->{shell}='' );
}
# $error = $self->ut_textn('finger');
@@ -908,12 +862,13 @@ sub _check_duplicate {
or die dbh->errstr;
warn "$me acquired svc_acct table lock for duplicate search" if $DEBUG;
- my $part_svc = qsearchs('part_svc', { 'svcpart' => $self->svcpart } );
+ my $svcpart = $self->svcpart;
+ my $part_svc = qsearchs('part_svc', { 'svcpart' => $svcpart } );
unless ( $part_svc ) {
return 'unknown svcpart '. $self->svcpart;
}
- my $global_unique = $conf->config('global_unique-username') || 'none';
+ my $global_unique = $conf->config('global_unique-username');
my @dup_user = grep { !$self->svcnum || $_->svcnum != $self->svcnum }
qsearch( 'svc_acct', { 'username' => $self->username } );
@@ -929,7 +884,7 @@ sub _check_duplicate {
my @dup_uid;
if ( $part_svc->part_svc_column('uid')->columnflag ne 'F'
&& $self->username !~ /^(toor|(hyla)?fax)$/ ) {
- @dup_uid = grep { !$self->svcnum || $_->svcnum != $self->svcnum }
+ @dup_uid = grep { $svcpart != $_->svcpart }
qsearch( 'svc_acct', { 'uid' => $self->uid } );
} else {
@dup_uid = ();
@@ -990,8 +945,8 @@ sub _check_duplicate {
my $dup_svcpart = $dup_uid->cust_svc->svcpart;
if ( exists($conflict_user_svcpart{$dup_svcpart})
|| exists($conflict_userdomain_svcpart{$dup_svcpart}) ) {
- return "duplicate uid: conflicts with svcnum ". $dup_uid->svcnum.
- " via exportnum ". $conflict_user_svcpart{$dup_svcpart}
+ return "duplicate uid: conflicts with svcnum". $dup_uid->svcnum.
+ "via exportnum ". $conflict_user_svcpart{$dup_svcpart}
|| $conflict_userdomain_svcpart{$dup_svcpart};
}
}
@@ -1026,10 +981,6 @@ expected to change in the future.
sub radius_reply {
my $self = shift;
-
- return %{ $self->{'radius_reply'} }
- if exists $self->{'radius_reply'};
-
my %reply =
map {
/^(radius_(.*))$/;
@@ -1037,15 +988,9 @@ sub radius_reply {
#$attrib =~ s/_/\-/g;
( $FS::raddb::attrib{lc($attrib)}, $self->getfield($column) );
} grep { /^radius_/ && $self->getfield($_) } fields( $self->table );
-
if ( $self->slipip && $self->slipip ne '0e0' ) {
$reply{$radius_ip} = $self->slipip;
}
-
- if ( $self->seconds !~ /^$/ ) {
- $reply{'Session-Timeout'} = $self->seconds;
- }
-
%reply;
}
@@ -1062,63 +1007,16 @@ expected to change in the future.
sub radius_check {
my $self = shift;
-
- return %{ $self->{'radius_check'} }
- if exists $self->{'radius_check'};
-
- my %check =
+ my $password = $self->_password;
+ my $pw_attrib = length($password) <= 12 ? $radius_password : 'Crypt-Password';
+ ( $pw_attrib => $password,
map {
/^(rc_(.*))$/;
my($column, $attrib) = ($1, $2);
#$attrib =~ s/_/\-/g;
( $FS::raddb::attrib{lc($attrib)}, $self->getfield($column) );
- } grep { /^rc_/ && $self->getfield($_) } fields( $self->table );
-
- my $password = $self->_password;
- my $pw_attrib = length($password) <= 12 ? $radius_password : 'Crypt-Password'; $check{$pw_attrib} = $password;
-
- my $cust_pkg = $self->cust_svc->cust_pkg;
- if ( $cust_pkg && $cust_pkg->part_pkg->is_prepaid && $cust_pkg->bill ) {
- $check{'Expiration'} = time2str('%B %e %Y %T', $cust_pkg->bill ); #http://lists.cistron.nl/pipermail/freeradius-users/2005-January/040184.html
- }
-
- %check;
-
-}
-
-=item snapshot
-
-This method instructs the object to "snapshot" or freeze RADIUS check and
-reply attributes to the current values.
-
-=cut
-
-#bah, my english is too broken this morning
-#Of note is the "Expiration" attribute, which, for accounts in prepaid packages, is typically defined on-the-fly as the associated packages cust_pkg.bill. (This is used by
-#the FS::cust_pkg's replace method to trigger the correct export updates when
-#package dates change)
-
-sub snapshot {
- my $self = shift;
-
- $self->{$_} = { $self->$_() }
- foreach qw( radius_reply radius_check );
-
-}
-
-=item forget_snapshot
-
-This methos instructs the object to forget any previously snapshotted
-RADIUS check and reply attributes.
-
-=cut
-
-sub forget_snapshot {
- my $self = shift;
-
- delete $self->{$_}
- foreach qw( radius_reply radius_check );
-
+ } grep { /^rc_/ && $self->getfield($_) } fields( $self->table )
+ );
}
=item domain
@@ -1155,7 +1053,10 @@ Returns the FS::cust_svc record for this account (see L<FS::cust_svc>).
=cut
-#inherited from svc_Common
+sub cust_svc {
+ my $self = shift;
+ qsearchs( 'cust_svc', { 'svcnum' => $self->svcnum } );
+}
=item email
@@ -1184,93 +1085,6 @@ sub acct_snarf {
qsearch('acct_snarf', { 'svcnum' => $self->svcnum } );
}
-=item decrement_seconds SECONDS
-
-Decrements the I<seconds> field of this record by the given amount. If there
-is an error, returns the error, otherwise returns false.
-
-=cut
-
-sub decrement_seconds {
- shift->_op_seconds('-', @_);
-}
-
-=item increment_seconds SECONDS
-
-Increments the I<seconds> field of this record by the given amount. If there
-is an error, returns the error, otherwise returns false.
-
-=cut
-
-sub increment_seconds {
- shift->_op_seconds('+', @_);
-}
-
-
-my %op2action = (
- '-' => 'suspend',
- '+' => 'unsuspend',
-);
-my %op2condition = (
- '-' => sub { my($self, $seconds) = @_;
- $self->seconds - $seconds <= 0;
- },
- '+' => sub { my($self, $seconds) = @_;
- $self->seconds + $seconds > 0;
- },
-);
-
-sub _op_seconds {
- my( $self, $op, $seconds ) = @_;
- warn "$me _op_seconds called for svcnum ". $self->svcnum.
- ' ('. $self->email. "): $op $seconds\n"
- if $DEBUG;
-
- 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 $sql = "UPDATE svc_acct SET seconds = ".
- " CASE WHEN seconds IS NULL THEN 0 ELSE seconds END ". #$seconds||0
- " $op ? WHERE svcnum = ?";
- warn "$me $sql\n"
- if $DEBUG;
-
- my $sth = $dbh->prepare( $sql )
- or die "Error preparing $sql: ". $dbh->errstr;
- my $rv = $sth->execute($seconds, $self->svcnum);
- die "Error executing $sql: ". $sth->errstr
- unless defined($rv);
- die "Can't update seconds for svcnum". $self->svcnum
- if $rv == 0;
-
- my $action = $op2action{$op};
-
- if ( $conf->exists("svc_acct-usage_$action")
- && &{$op2condition{$op}}($self, $seconds) ) {
- #my $error = $self->$action();
- my $error = $self->cust_svc->cust_pkg->$action();
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "Error ${action}ing: $error";
- }
- }
-
- warn "$me update sucessful; committing\n"
- if $DEBUG;
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-
=item seconds_since TIMESTAMP
Returns the number of seconds this account has been online since TIMESTAMP,
@@ -1329,16 +1143,16 @@ sub attribute_since_sqlradacct {
$self->cust_svc->attribute_since_sqlradacct(@_);
}
-=item get_session_history TIMESTAMP_START TIMESTAMP_END
+=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 {
+sub get_session_history_sqlradacct {
my $self = shift;
- $self->cust_svc->get_session_history(@_);
+ $self->cust_svc->get_session_history_sqlradacct(@_);
}
=item radius_groups
@@ -1424,43 +1238,25 @@ sub check_password {
}
-=item crypt_password [ DEFAULT_ENCRYPTION_TYPE ]
+=item crypt_password
Returns an encrypted password, either by passing through an encrypted password
in the database or by encrypting a plaintext password from the database.
-The optional DEFAULT_ENCRYPTION_TYPE parameter can be set to I<crypt> (classic
-UNIX DES crypt), I<md5> (md5 crypt supported by most modern Linux and BSD
-distrubtions), or (eventually) I<blowfish> (blowfish hashing supported by
-OpenBSD, SuSE, other Linux distibutions with pam_unix2, etc.). The default
-encryption type is only used if the password is not already encrypted in the
-database.
-
=cut
sub crypt_password {
my $self = shift;
+ #false laziness w/shellcommands.pm
#eventually should check a "password-encoding" field
if ( length($self->_password) == 13
- || $self->_password =~ /^\$(1|2a?)\$/
- || $self->_password =~ /^(\*|NP|\*LK\*|!!?)$/
- )
- {
+ || $self->_password =~ /^\$(1|2a?)\$/ ) {
$self->_password;
} else {
- my $encryption = ( scalar(@_) && $_[0] ) ? shift : 'crypt';
- if ( $encryption eq 'crypt' ) {
- crypt(
- $self->_password,
- $saltset[int(rand(64))].$saltset[int(rand(64))]
- );
- } elsif ( $encryption eq 'md5' ) {
- unix_md5_crypt( $self->_password );
- } elsif ( $encryption eq 'blowfish' ) {
- die "unknown encryption method $encryption";
- } else {
- die "unknown encryption method $encryption";
- }
+ crypt(
+ $self->_password,
+ $saltset[int(rand(64))].$saltset[int(rand(64))]
+ );
}
}
@@ -1619,7 +1415,7 @@ sub radius_usergroup_selector {
END
foreach my $group ( @all_groups ) {
- $html .= qq(<OPTION VALUE="$group");
+ $html .= '<OPTION';
if ( $sel_groups{$group} ) {
$html .= ' SELECTED';
$sel_groups{$group} = 0;
@@ -1627,7 +1423,7 @@ END
$html .= ">$group</OPTION>\n";
}
foreach my $group ( grep { $sel_groups{$_} } keys %sel_groups ) {
- $html .= qq(<OPTION VALUE="$group" SELECTED>$group</OPTION>\n);
+ $html .= "<OPTION SELECTED>$group</OPTION>\n";
};
$html .= '</SELECT>';
diff --git a/FS/FS/svc_domain.pm b/FS/FS/svc_domain.pm
index 6d5435718..2642146ea 100644
--- a/FS/FS/svc_domain.pm
+++ b/FS/FS/svc_domain.pm
@@ -369,7 +369,6 @@ sub domain_record {
MX => 3,
CNAME => 4,
A => 5,
- TXT => 6,
);
sort { $order{$a->rectype} <=> $order{$b->rectype} }
diff --git a/FS/FS/svc_forward.pm b/FS/FS/svc_forward.pm
index 12b556f33..b8d55fecb 100644
--- a/FS/FS/svc_forward.pm
+++ b/FS/FS/svc_forward.pm
@@ -249,15 +249,15 @@ sub check {
# || ! $self->dstsvc;
if ( $self->src ) {
- $self->src =~ /^([\w\.\-\&]*)(\@([\w\-]+\.)+\w+)$/
- or return "Illegal src: ". $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");
} else {
diff --git a/FS/FS/svc_www.pm b/FS/FS/svc_www.pm
index 12d7e92f3..6c276a198 100644
--- a/FS/FS/svc_www.pm
+++ b/FS/FS/svc_www.pm
@@ -204,7 +204,7 @@ sub check {
my $error =
$self->ut_numbern('svcnum')
# || $self->ut_number('recnum')
- || $self->ut_numbern('usersvc')
+ || $self->ut_number('usersvc')
;
return $error if $error;
@@ -238,10 +238,8 @@ sub check {
return "Illegal recnum: ". $self->recnum;
}
- if ( $self->usersvc ) {
- return "Unknown usersvc0 (svc_acct.svcnum): ". $self->usersvc
- unless qsearchs('svc_acct', { 'svcnum' => $self->usersvc } );
- }
+ return "Unknown usersvc (svc_acct.svcnum): ". $self->usersvc
+ unless qsearchs('svc_acct', { 'svcnum' => $self->usersvc } );
$self->SUPER::check;
diff --git a/FS/FS/type_pkgs.pm b/FS/FS/type_pkgs.pm
index bf34e7cda..07ad2bc2b 100644
--- a/FS/FS/type_pkgs.pm
+++ b/FS/FS/type_pkgs.pm
@@ -35,8 +35,6 @@ FS::Record. The following fields are currently supported:
=over 4
-=item typepkgnum - primary key
-
=item typenum - Agent type, see L<FS::agent_type>
=item pkgpart - Billing item definition, see L<FS::part_pkg>
@@ -82,8 +80,7 @@ sub check {
my $self = shift;
my $error =
- $self->ut_numbern('typepkgnum')
- || $self->ut_number('typenum')
+ $self->ut_number('typenum')
|| $self->ut_number('pkgpart')
;
return $error if $error;
diff --git a/FS/MANIFEST b/FS/MANIFEST
index e7d9dea34..32785c20e 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -28,19 +28,20 @@ FS.pm
FS/CGI.pm
FS/InitHandler.pm
FS/ClientAPI.pm
-FS/ClientAPI_SessionCache.pm
FS/ClientAPI/passwd.pm
FS/ClientAPI/MyAccount.pm
FS/Conf.pm
FS/ConfItem.pm
-FS/Daemon.pm
FS/Misc.pm
FS/Record.pm
FS/Report.pm
FS/Report/Table.pm
FS/Report/Table/Monthly.pm
FS/SearchCache.pm
-FS/UI/Web.pm
+FS/UI/Base.pm
+FS/UI/CGI.pm
+FS/UI/Gtk.pm
+FS/UI/agent.pm
FS/UID.pm
FS/Msgcat.pm
FS/acct_snarf.pm
@@ -52,7 +53,6 @@ FS/cust_bill_pkg_detail.pm
FS/cust_credit.pm
FS/cust_credit_bill.pm
FS/cust_main.pm
-FS/cust_main_Mixin.pm
FS/cust_main_county.pm
FS/cust_main_invoice.pm
FS/cust_pay.pm
@@ -66,7 +66,6 @@ FS/cust_credit_refund.pm
FS/cust_svc.pm
FS/h_Common.pm
FS/h_cust_svc.pm
-FS/h_domain_record.pm
FS/h_svc_acct.pm
FS/h_svc_broadband.pm
FS/h_svc_domain.pm
@@ -92,8 +91,6 @@ FS/part_export/http.pm
FS/part_export/infostreet.pm
FS/part_export/ldap.pm
FS/part_export/null.pm
-FS/part_export/radiator.pm
-FS/part_export/router.pm
FS/part_export/shellcommands.pm
FS/part_export/shellcommands_withdomain.pm
FS/part_export/sqlmail.pm
@@ -128,8 +125,6 @@ FS/rate.pm
FS/rate_detail.pm
FS/rate_region.pm
FS/rate_prefix.pm
-FS/reg_code.pm
-FS/reg_code_pkg.pm
FS/svc_Common.pm
FS/svc_acct.pm
FS/svc_acct_pop.pm
@@ -152,17 +147,13 @@ FS/queue_arg.pm
FS/queue_depend.pm
FS/msgcat.pm
FS/cust_tax_exempt.pm
-FS/clientapi_session.pm
-FS/clientapi_session_field.pm
t/agent.t
t/agent_type.t
t/CGI.t
t/InitHandler.t
t/ClientAPI.t
-t/ClientAPI_SessionCache.t
t/Conf.t
t/ConfItem.t
-t/Daemon.t
t/Misc.t
t/Record.t
t/Report.t
@@ -180,7 +171,6 @@ t/cust_credit.t
t/cust_credit_bill.t
t/cust_credit_refund.t
t/cust_main.t
-t/cust_main_Mixin.t
t/cust_main_county.t
t/cust_main_invoice.t
t/cust_pay.t
@@ -192,7 +182,6 @@ t/cust_svc.t
t/h_cust_svc.t
t/h_Common.t
t/h_cust_svc.t
-t/h_domain_record.t
t/h_svc_acct.t
t/h_svc_broadband.t
t/h_svc_domain.t
@@ -223,7 +212,6 @@ t/part_export-ldap.t
t/part_export-null.t
t/part_export-passwdfile.t
t/part_export-postfix.t
-t/part_export-radiator.t
t/part_export-router.t
t/part_export-shellcommands.t
t/part_export-shellcommands_withdomain.t
@@ -260,8 +248,6 @@ t/rate_detail.t
t/rate_region.t
t/rate_prefix.t
t/radius_usergroup.t
-t/reg_code.t
-t/reg_code_pkg.t
t/session.t
t/svc_acct.t
t/svc_acct_pop.t
@@ -277,18 +263,3 @@ t/queue_arg.t
t/queue_depend.t
t/msgcat.t
t/raddb.t
-t/clientapi_session.t
-t/clientapi_session_field.t
-FS/payment_gateway.pm
-t/payment_gateway.t
-FS/payment_gateway_option.pm
-t/payment_gateway_option.t
-FS/option_Common.pm
-t/option_Common.t
-FS/agent_payment_gateway.pm
-t/agent_payment_gateway.t
-FS/banned_pay.pm
-t/banned_pay.t
-FS/cancel_reason.pm
-t/cancel_reason.t
-bin/freeside-prepaidd
diff --git a/FS/bin/freeside-addoutsource b/FS/bin/freeside-addoutsource
index db4e7a307..5cec17f46 100644
--- a/FS/bin/freeside-addoutsource
+++ b/FS/bin/freeside-addoutsource
@@ -4,21 +4,21 @@ domain=$1
createdb $domain && \
\
-mkdir /usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain && \
+mkdir /usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain && \
\
-chown freeside /usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain && \
+chown freeside /usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain && \
\
-cp /home/ivan/freeside/conf/[a-z]* /usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain && \
+cp /home/ivan/freeside/conf/[a-z]* /usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain && \
\
-touch /usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain/secrets && \
+touch /usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain/secrets && \
\
-chown freeside /usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain/secrets && \
+chown freeside /usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain/secrets && \
\
-chmod 600 /usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain/secrets && \
+chmod 600 /usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain/secrets && \
\
-echo -e "DBI:Pg:dbname=$domain\nfreeside\n" >/usr/local/etc/freeside/conf.DBI:Pg:dbname=$domain/secrets && \
+echo -e "DBI:Pg:host=localhost;dbname=$domain\nfreeside\n" >/usr/local/etc/freeside/conf.DBI:Pg:host=localhost\;dbname=$domain/secrets && \
\
-mkdir /usr/local/etc/freeside/counters.DBI:Pg:dbname=$domain && \
-mkdir /usr/local/etc/freeside/cache.DBI:Pg:dbname=$domain && \
-mkdir /usr/local/etc/freeside/export.DBI:Pg:dbname=$domain
+mkdir /usr/local/etc/freeside/counters.DBI:Pg:host=localhost\;dbname=$domain && \
+mkdir /usr/local/etc/freeside/cache.DBI:Pg:host=localhost\;dbname=$domain && \
+mkdir /usr/local/etc/freeside/export.DBI:Pg:host=localhost\;dbname=$domain
diff --git a/FS/bin/freeside-addoutsourceuser b/FS/bin/freeside-addoutsourceuser
index cad07f1fd..abb515b6f 100644
--- a/FS/bin/freeside-addoutsourceuser
+++ b/FS/bin/freeside-addoutsourceuser
@@ -5,11 +5,11 @@ domain=$2
password=$3
freeside-adduser -h /usr/local/etc/freeside/htpasswd \
- -s conf.DBI:Pg:dbname=$domain/secrets \
+ -s conf.DBI:Pg:host=localhost\;dbname=$domain/secrets \
-b \
$username $password 2>/dev/null
-[ -e /usr/local/etc/freeside/dbdef.DBI:Pg:dbname=$domain ] \
+[ -e /usr/local/etc/freeside/dbdef.DBI:Pg:host=localhost\;dbname=$domain ] \
|| ( 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 603da12b8..ae71112dd 100755
--- a/FS/bin/freeside-daily
+++ b/FS/bin/freeside-daily
@@ -5,78 +5,31 @@ use Fcntl qw(:flock);
use Date::Parse;
use Getopt::Std;
use FS::UID qw(adminsuidsetup driver_name dbh datasrc);
-use FS::Record qw(qsearch qsearchs dbdef);
+use FS::Record qw(qsearch qsearchs);
use FS::Conf;
use FS::cust_main;
&untaint_argv; #what it sounds like (eww)
-use vars qw($opt_d $opt_v $opt_p $opt_a $opt_s $opt_y);
-getopts("p:a:d:vsy:");
+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;
$FS::cust_main::DEBUG = 1 if $opt_v;
-my %search = ();
-$search{'payby'} = $opt_p if $opt_p;
-$search{'agentnum'} = $opt_a if $opt_a;
+my %search;
+$search{'payby'} = $opt_p if $opt_p;
+
+my @cust_main = @ARGV
+ ? map { qsearchs('cust_main', { custnum => $_, %search } ) } @ARGV
+ : qsearch('cust_main', \%search )
+;
#we're at now now (and later).
my($time)= $opt_d ? str2time($opt_d) : $^T;
$time += $opt_y * 86400 if $opt_y;
-# select * from cust_main where
-my $where_pkg = <<"END";
- 0 < ( select count(*) from cust_pkg
- where cust_main.custnum = cust_pkg.custnum
- and ( cancel is null or cancel = 0 )
- and ( setup is null or setup = 0
- or bill is null or bill <= $time
- or ( expire is not null and expire <= $^T )
- )
- )
-END
-
-# or
-my $where_bill_event = <<"END";
- 0 < ( select count(*) from cust_bill
- where cust_main.custnum = cust_bill.custnum
- and 0 < charged
- - coalesce(
- ( select sum(amount) from cust_bill_pay
- where cust_bill.invnum = cust_bill_pay.invnum )
- ,0
- )
- - coalesce(
- ( select sum(amount) from cust_credit_bill
- where cust_bill.invnum = cust_credit_bill.invnum )
- ,0
- )
- and 0 < ( select count(*) from part_bill_event
- where payby = cust_main.payby
- and ( disabled is null or disabled = '' )
- and seconds <= $time - cust_bill._date
- and 0 = ( select count(*) from cust_bill_event
- where cust_bill.invnum = cust_bill_event.invnum
- and part_bill_event.eventpart = cust_bill_event.eventpart
- and status = 'done'
- )
-
- )
- )
-END
-
-my $extra_sql = ( scalar(%search) ? ' AND ' : ' WHERE ' ). "( $where_pkg OR $where_bill_event )";
-
-my @cust_main;
-if ( @ARGV ) {
- @cust_main = map { qsearchs('cust_main', { custnum => $_, %search } ) } @ARGV
-} else {
- @cust_main = qsearch('cust_main', \%search, '', $extra_sql );
-}
-;
-
my($cust_main,%saw);
foreach $cust_main ( @cust_main ) {
@@ -89,19 +42,6 @@ foreach $cust_main ( @cust_main ) {
$cust_main->custnum. ": $error"
if $error;
}
- # $^T not $time because -d is for pre-printing invoices
- foreach my $cust_pkg (
- grep { $_->part_pkg->is_prepaid
- && $_->bill && $_->bill < $^T && ! $_->susp
- }
- $cust_main->ncancelled_pkgs
- ) {
- my $error = $cust_pkg->suspend;
- warn "Error suspending package ". $cust_pkg->pkgnum.
- " for custnum ". $cust_main->custnum.
- ": $error"
- if $error;
- }
my $error = $cust_main->bill( 'time' => $time,
'resetup' => $opt_s, );
@@ -117,10 +57,8 @@ foreach $cust_main ( @cust_main ) {
if ( driver_name eq 'Pg' ) {
dbh->{AutoCommit} = 1; #so we can vacuum
- foreach my $table ( dbdef->tables ) {
- my $sth = dbh->prepare("VACUUM ANALYZE $table") or die dbh->errstr;
- $sth->execute or die $sth->errstr;
- }
+ my $sth = dbh->prepare('vacuum analyze') or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
}
my $conf = new FS::Conf;
@@ -172,7 +110,7 @@ freeside-daily - Run daily billing and invoice collection events.
=head1 SYNOPSIS
- freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -a agentnum ] [ -s ] [ -v ] user [ custnum custnum ... ]
+ freeside-daily [ -d 'date' ] [ -y days ] [ -p 'payby' ] [ -s ] [ -v ] user [ custnum custnum ... ]
=head1 DESCRIPTION
@@ -194,8 +132,6 @@ the bill and collect methods of a cust_main object. See L<FS::cust_main>.
-p: Only process customers with the specified payby (I<CARD>, I<DCRD>, I<CHEK>, I<DCHK>, I<BILL>, I<COMP>, I<LECB>)
- -a: Only process customers with the specified agentnum
-
-s: re-charge setup fees
-v: enable debugging
diff --git a/FS/bin/freeside-prepaidd b/FS/bin/freeside-prepaidd
deleted file mode 100644
index e51a56350..000000000
--- a/FS/bin/freeside-prepaidd
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
-use FS::UID qw(adminsuidsetup);
-use FS::Record qw(qsearch); # qsearchs);
-use FS::cust_pkg;
-
-my $user = shift or die &usage;
-
-#daemonize1('freeside-sprepaidd', $user); #keep unique pid files w/multi installs
-daemonize1('freeside-prepaidd');
-
-drop_root();
-
-adminsuidsetup($user);
-
-logfile( "/usr/local/etc/freeside/prepaidd-log.". $FS::UID::datasrc );
-
-daemonize2();
-
-#--
-
-while (1) {
-
- foreach my $cust_pkg (
- qsearch( {
- 'select' => 'cust_pkg.*, part_pkg.plan',
- 'table' => 'cust_pkg',
- 'addl_from' => 'LEFT JOIN part_pkg USING ( pkgpart )',
- #'hashref' => { 'plan' => 'prepaid' },#should check part_pkg::is_prepaid
- #'extra_sql' => "AND bill < ". time.
- 'hashref' => {},
- 'extra_sql' => "WHERE plan = 'prepaid' AND bill < ". time.
- " AND bill IS NOT NULL".
- " AND ( susp IS NULL OR susp = 0)".
- " AND ( cancel IS NULL OR cancel = 0)"
- } )
- ) {
- my $error = $cust_pkg->suspend;
- warn "Error suspended package ". $cust_pkg->pkgnum.
- " for custnum ". $cust_pkg->custnum.
- ": $error\n"
- if $error;
- }
-
- die "exiting" if sigterm() || sigint();
- sleep 5;
-
-}
-
-#--
-
-sub usage {
- die "Usage:\n\n freeside-prepaidd user\n";
-}
-
-=head1 NAME
-
-freeside-prepaidd - Real-time daemon for prepaid packages
-
-=head1 SYNOPSIS
-
- freeside-prepaidd
-
-=head1 DESCRIPTION
-
-Runs continuously and suspendes any prepaid customer packages which have
-passed their renewal date (next bill date).
-
-=head1 SEE ALSO
-
-=cut
-
-1;
diff --git a/FS/bin/freeside-queued b/FS/bin/freeside-queued
index 3a0a9b4e5..e14ddad8e 100644
--- a/FS/bin/freeside-queued
+++ b/FS/bin/freeside-queued
@@ -1,11 +1,13 @@
#!/usr/bin/perl -w
use strict;
-use vars qw( $DEBUG $kids $max_kids %kids );
-use POSIX qw(:sys_wait_h);
+use vars qw( $log_file $sigterm $sigint $kids $max_kids %kids );
+use subs qw( _die _logmsg );
+use Fcntl qw(:flock);
+use POSIX qw(:sys_wait_h setsid);
+use Date::Format;
use IO::File;
use FS::UID qw(adminsuidsetup forksuidsetup driver_name dbh myconnect);
-use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
use FS::Record qw(qsearch qsearchs);
use FS::queue;
use FS::queue_depend;
@@ -16,24 +18,40 @@ use FS::svc_acct;
use Net::SSH 0.07;
use FS::part_export;
-$DEBUG = 0;
-
$max_kids = '10'; #guess it should be a config file...
$kids = 0;
my $user = shift or die &usage;
-warn "starting daemonization (forking)\n" if $DEBUG;
-#daemonize1('freeside-queued',$user); #to keep pid files unique w/multi installs
-daemonize1('freeside-queued');
+#my $pid_file = "/var/run/freeside-queued.$user.pid";
+my $pid_file = "/var/run/freeside-queued.pid";
+
+&daemonize1;
+
+#sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; $kids--; }
+#$SIG{CHLD} = \&REAPER;
-warn "dropping privledges\n" if $DEBUG;
-drop_root();
+$sigterm = 0;
+$sigint = 0;
+$SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; };
+$SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
+my $freeside_gid = scalar(getgrnam('freeside'))
+ or die "can't setgid to freeside group\n";
+$) = $freeside_gid;
+$( = $freeside_gid;
+#if freebsd can't setuid(), presumably it can't setgid() either. grr fleabsd
+($(,$)) = ($),$();
+$) = $freeside_gid;
+
+$> = $FS::UID::freeside_uid;
+$< = $FS::UID::freeside_uid;
+#freebsd is sofa king broken, won't setuid()
+($<,$>) = ($>,$<);
+$> = $FS::UID::freeside_uid;
$ENV{HOME} = (getpwuid($>))[7]; #for ssh
-warn "connecting to database\n" if $DEBUG;
$@ = 'not connected';
while ( $@ ) {
eval { adminsuidsetup $user; };
@@ -44,12 +62,14 @@ while ( $@ ) {
}
}
-logfile( "/usr/local/etc/freeside/queuelog.". $FS::UID::datasrc );
+$log_file = "/usr/local/etc/freeside/queuelog.". $FS::UID::datasrc;
+
+&daemonize2;
-warn "completing daemonization (detaching))\n" if $DEBUG;
-daemonize2();
+$SIG{__DIE__} = \&_die;
+$SIG{__WARN__} = \&_logmsg;
-#--
+warn "freeside-queued starting\n";
my $warnkids=0;
while (1) {
@@ -67,7 +87,7 @@ while (1) {
unless ( dbh && dbh->ping ) {
warn "WARNING: connection to database lost, reconnecting...\n";
- eval { $FS::UID::dbh = myconnect; };
+ eval { myconnect; };
unless ( !$@ && dbh && dbh->ping ) {
warn "WARNING: still no connection to database, sleeping for retry...\n";
@@ -142,7 +162,6 @@ while (1) {
#}
my @args = $ljob->args;
- splice @args, 0, 1, $ljob if $args[0] eq '_JOB';
defined( my $pid = fork ) or do {
warn "WARNING: can't fork: $!\n";
@@ -165,12 +184,8 @@ while (1) {
forksuidsetup($user);
- #auto-use classes...
- #if ( $ljob->job =~ /(FS::part_export::\w+)::/ ) {
- if ( $ljob->job =~ /(FS::part_export::\w+)::/
- || $ljob->job =~ /(FS::\w+)::/
- )
- {
+ #auto-use export classes...
+ if ( $ljob->job =~ /(FS::part_export::\w+)::/ ) {
my $class = $1;
eval "use $class;";
if ( $@ ) {
@@ -186,7 +201,7 @@ while (1) {
}
my $eval = "&". $ljob->job. '(@args);';
- warn 'running "&'. $ljob->job. '('. join(', ', @args). ")\n" if $DEBUG;
+ warn "running $eval";
eval $eval; #throw away return value? suppose so
if ( $@ ) {
warn "job $eval failed";
@@ -205,11 +220,11 @@ while (1) {
}
} continue {
- if ( sigterm() ) {
+ if ( $sigterm ) {
warn "received TERM signal; exiting\n";
exit;
}
- if ( sigint() ) {
+ if ( $sigint ) {
warn "received INT signal; exiting\n";
exit;
}
@@ -219,6 +234,48 @@ sub usage {
die "Usage:\n\n freeside-queued user\n";
}
+sub _die {
+ my $msg = shift;
+ unlink $pid_file if -e $pid_file;
+ _logmsg($msg);
+}
+
+sub _logmsg {
+ chomp( my $msg = shift );
+ my $log = new IO::File ">>$log_file";
+ flock($log, LOCK_EX);
+ seek($log, 0, 2);
+ print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
+ flock($log, LOCK_UN);
+ close $log;
+}
+
+sub daemonize1 {
+
+ chdir "/" or die "Can't chdir to /: $!";
+ open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
+ defined(my $pid = fork) or die "Can't fork: $!";
+ if ( $pid ) {
+ print "freeside-queued started with pid $pid\n"; #logging to $log_file\n";
+ exit unless $pid_file;
+ my $pidfh = new IO::File ">$pid_file" or exit;
+ print $pidfh "$pid\n";
+ exit;
+ }
+ #open STDOUT, '>/dev/null'
+ # or die "Can't write to /dev/null: $!";
+ #setsid or die "Can't start a new session: $!";
+ #open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
+
+}
+
+sub daemonize2 {
+ open STDOUT, '>/dev/null'
+ or die "Can't write to /dev/null: $!";
+ setsid or die "Can't start a new session: $!";
+ open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
+}
+
sub reap_kids {
foreach my $pid ( keys %kids ) {
my $kid = waitpid($pid, WNOHANG);
diff --git a/FS/bin/freeside-selfservice-server b/FS/bin/freeside-selfservice-server
index c73349a60..c045893d1 100644
--- a/FS/bin/freeside-selfservice-server
+++ b/FS/bin/freeside-selfservice-server
@@ -1,16 +1,23 @@
#!/usr/bin/perl -w
+#
+# freeside-selfservice-server
+
+# alas, much false laziness with freeside-queued and fs_signup_server. at
+# least it is slated to replace fs_{signup,passwd,mailadmin}_server
+# should probably generalize the version in here, or better yet use
+# Proc::Daemon or somesuch
use strict;
-use vars qw( $Debug %kids $kids $max_kids $ssh_pid $keepalives );
-use subs qw( lock_write unlock_write myshutdown usage );
+use vars qw( $Debug %kids $kids $max_kids $shutdown $log_file $ssh_pid
+ $keepalives );
+use subs qw( lock_write unlock_write );
use Fcntl qw(:flock);
-use POSIX qw(:sys_wait_h);
+use POSIX qw(:sys_wait_h setsid);
use IO::Handle;
use IO::Select;
use IO::File;
use Storable 2.09 qw(nstore_fd fd_retrieve);
use Net::SSH qw(sshopen2);
-use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
use FS::UID qw(adminsuidsetup forksuidsetup);
use FS::ClientAPI;
@@ -21,6 +28,7 @@ use FS::cust_pkg;
$Debug = 1; # 2 will turn on more logging
# 3 will log packet contents, including passwords
+$shutdown = 0;
$max_kids = '10'; #?
$keepalives = 0; #let clientd turn it on, so we don't barf on old ones
$kids = 0;
@@ -29,31 +37,12 @@ my $user = shift or die &usage;
my $machine = shift or die &usage;
my $tag = scalar(@ARGV) ? shift : '';
-my $lock_file = "/usr/local/etc/freeside/selfservice.$machine.writelock";
-
-
-# to keep pid files unique w/multi machines (and installs!)
# $FS::UID::datasrc not posible
-daemonize1("freeside-selfservice-server","$user.$machine");
-
-#false laziness w/Daemon::drop_root
-my $freeside_gid = scalar(getgrnam('freeside'))
- or die "can't find freeside group\n";
-
-open(LOCKFILE,">$lock_file") or die "can't open $lock_file: $!";
-chown $FS::UID::freeside_uid, $freeside_gid, $lock_file;
-
-drop_root();
-
-$ENV{HOME} = (getpwuid($>))[7]; #for ssh
+my $pid_file = "/var/run/freeside-selfservice-server.$user.$machine.pid";
-adminsuidsetup $user;
-
-#logfile("/usr/local/etc/freeside/selfservice.". $FS::UID::datasrc); #MACHINE
-logfile("/usr/local/etc/freeside/selfservice.$machine.log");
-
-daemonize2();
+my $lock_file = "/usr/local/etc/freeside/selfservice.$machine.writelock";
+&init($user);
my $conf = new FS::Conf;
@@ -80,7 +69,7 @@ while (1) {
$undisp = 1;
my @handles = $s->can_read(5);
unless ( @handles ) {
- myshutdown() if sigint() || sigterm();
+ &shutdown if $shutdown;
if ( $keepalives && $keepalive_count++ > 10 ) {
$keepalive_count = 0;
lock_write;
@@ -161,7 +150,7 @@ while (1) {
}
- myshutdown if sigint() || sigterm();
+ &shutdown if $shutdown;
warn "connection lost, reconnecting\n" if $Debug;
sleep 3;
@@ -183,7 +172,70 @@ sub reap_kids {
#warn "done reaping\n";
}
-sub myshutdown {
+sub init {
+ my $user = shift;
+
+ chdir "/" or die "Can't chdir to /: $!";
+ open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
+ defined(my $pid = fork) or die "Can't fork: $!";
+ if ( $pid ) {
+ print "freeside-selfservice-server to $machine started with pid $pid\n"; #logging to $log_file
+ exit unless $pid_file;
+ my $pidfh = new IO::File ">$pid_file" or exit;
+ print $pidfh "$pid\n";
+ exit;
+ }
+
+# sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; $kids--; }
+# #sub REAPER { my $pid = wait; $kids--; $SIG{CHLD} = \&REAPER; }
+# $SIG{CHLD} = \&REAPER;
+
+ $shutdown = 0;
+ $SIG{HUP} = sub { warn "SIGHUP received; shutting down\n"; $shutdown++; };
+ $SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $shutdown++; };
+ $SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $shutdown++; };
+ $SIG{QUIT} = sub { warn "SIGQUIT received; shutting down\n"; $shutdown++; };
+ $SIG{PIPE} = sub { warn "SIGPIPE received; shutting down\n"; $shutdown++; };
+
+ #false laziness w/freeside-queued
+ my $freeside_gid = scalar(getgrnam('freeside'))
+ or die "can't setgid to freeside group\n";
+
+ open(LOCKFILE,">$lock_file") or die "can't open $lock_file: $!";
+ chown $FS::UID::freeside_uid, $freeside_gid, $lock_file;
+
+ $) = $freeside_gid;
+ $( = $freeside_gid;
+ #if freebsd can't setuid(), presumably it can't setgid() either. grr fleabsd
+ ($(,$)) = ($),$();
+ $) = $freeside_gid;
+
+ $> = $FS::UID::freeside_uid;
+ $< = $FS::UID::freeside_uid;
+ #freebsd is sofa king broken, won't setuid()
+ ($<,$>) = ($>,$<);
+ $> = $FS::UID::freeside_uid;
+ #eslaf
+
+ $ENV{HOME} = (getpwuid($>))[7]; #for ssh
+ adminsuidsetup $user;
+
+ #$log_file = "/usr/local/etc/freeside/selfservice.". $FS::UID::datasrc; #MACHINE NAME
+ $log_file = "/usr/local/etc/freeside/selfservice.$machine.log";
+
+ open STDOUT, '>/dev/null'
+ or die "Can't write to /dev/null: $!";
+ setsid or die "Can't start a new session: $!";
+ open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
+
+ $SIG{__DIE__} = \&_die;
+ $SIG{__WARN__} = \&_logmsg;
+
+ warn "freeside-selfservice-server starting\n";
+
+}
+
+sub shutdown {
&reap_kids;
my $wait = 12; #wait up to 1 minute
while ( $kids > 0 && $wait-- ) {
@@ -196,6 +248,27 @@ sub myshutdown {
die "exiting";
}
+sub _die {
+ my $msg = shift;
+ unlink $pid_file if -e $pid_file;
+ _logmsg($msg);
+}
+
+sub _logmsg {
+ chomp( my $msg = shift );
+ _do_logmsg( "[server] [". scalar(localtime). "] [$$] $msg\n" );
+}
+
+sub _do_logmsg {
+ chomp( my $msg = shift );
+ my $log = new IO::File ">>$log_file";
+ flock($log, LOCK_EX);
+ seek($log, 0, 2);
+ print $log "$msg\n";
+ flock($log, LOCK_UN);
+ close $log;
+}
+
sub lock_write {
warn "locking $lock_file mutex for write to write stream\n" if $Debug > 1;
diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup
index a16e51749..c867a721f 100755
--- a/FS/bin/freeside-setup
+++ b/FS/bin/freeside-setup
@@ -1,24 +1,29 @@
#!/usr/bin/perl -Tw
#to delay loading dbdef until we're ready
-BEGIN { $FS::Schema::setup_hack = 1; }
+BEGIN { $FS::Record::setup_hack = 1; }
use strict;
use vars qw($opt_s);
use Getopt::Std;
use Locale::Country;
use Locale::SubCountry;
+use DBI;
+use DBIx::DBSchema 0.21;
+use DBIx::DBSchema::Table;
+use DBIx::DBSchema::Column;
+use DBIx::DBSchema::ColGroup::Unique;
+use DBIx::DBSchema::ColGroup::Index;
use FS::UID qw(adminsuidsetup datasrc checkeuid getsecrets);
-use FS::Schema qw( dbdef_dist reload_dbdef );
use FS::Record;
use FS::cust_main_county;
-#use FS::raddb;
+use FS::raddb;
use FS::part_bill_event;
die "Not running uid freeside!" unless checkeuid();
-#my %attrib2db =
-# map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
+my %attrib2db =
+ map { lc($FS::raddb::attrib{$_}) => $_ } keys %FS::raddb::attrib;
getopts("s");
my $user = shift or die &usage;
@@ -70,25 +75,154 @@ my $username_len = 32; #usernamemax config file
# $x =~ /^y/i;
#}
-#my @check_attributes = (); #add later
-#my @attributes = (); #add later
-#my $ship = $opt_s;
+my @check_attributes = (); #add later
+my @attributes = (); #add later
+my $ship = $opt_s;
+
+###
+
+my($char_d) = 80; #default maxlength for text fields
+
+#my(@date_type) = ( 'timestamp', '', '' );
+my(@date_type) = ( 'int', 'NULL', '' );
+my(@perl_type) = ( 'text', 'NULL', '' );
+my @money_type = ( 'decimal', '', '10,2' );
###
# create a dbdef object from the old data structure
###
-my $dbdef = dbdef_dist;
+my(%tables)=&tables_hash_hack;
+
+#turn it into objects
+my($dbdef) = new DBIx::DBSchema ( map {
+ my(@columns);
+ while (@{$tables{$_}{'columns'}}) {
+ my($name,$type,$null,$length)=splice @{$tables{$_}{'columns'}}, 0, 4;
+ push @columns, new DBIx::DBSchema::Column ( $name,$type,$null,$length );
+ }
+ DBIx::DBSchema::Table->new(
+ $_,
+ $tables{$_}{'primary_key'},
+ DBIx::DBSchema::ColGroup::Unique->new($tables{$_}{'unique'}),
+ DBIx::DBSchema::ColGroup::Index->new($tables{$_}{'index'}),
+ @columns,
+ );
+} (keys %tables) );
+
+my $cust_main = $dbdef->table('cust_main');
+unless ($ship) { #remove ship_ from cust_main
+ $cust_main->delcolumn($_) foreach ( grep /^ship_/, $cust_main->columns );
+} else { #add indices
+ push @{$cust_main->index->lol_ref},
+ map { [ "ship_$_" ] } qw( last company daytime night fax );
+}
+
+#add radius attributes to svc_acct
+
+my($svc_acct)=$dbdef->table('svc_acct');
+
+my($attribute);
+foreach $attribute (@attributes) {
+ $svc_acct->addcolumn ( new DBIx::DBSchema::Column (
+ 'radius_'. $attribute,
+ 'varchar',
+ 'NULL',
+ $char_d,
+ ));
+}
+
+foreach $attribute (@check_attributes) {
+ $svc_acct->addcolumn( new DBIx::DBSchema::Column (
+ 'rc_'. $attribute,
+ 'varchar',
+ 'NULL',
+ $char_d,
+ ));
+}
+
+#create history tables (false laziness w/create-history-tables)
+foreach my $table ( grep { ! /^h_/ } $dbdef->tables ) {
+ my $tableobj = $dbdef->table($table)
+ or die "unknown table $table";
+
+ die "unique->lol_ref undefined for $table"
+ unless defined $tableobj->unique->lol_ref;
+ die "index->lol_ref undefined for $table"
+ unless defined $tableobj->index->lol_ref;
+
+ my $h_tableobj = DBIx::DBSchema::Table->new( {
+ name => "h_$table",
+ primary_key => 'historynum',
+ unique => DBIx::DBSchema::ColGroup::Unique->new( [] ),
+ 'index' => DBIx::DBSchema::ColGroup::Index->new( [
+ @{$tableobj->unique->lol_ref},
+ @{$tableobj->index->lol_ref}
+ ] ),
+ columns => [
+ DBIx::DBSchema::Column->new( {
+ 'name' => 'historynum',
+ 'type' => 'serial',
+ 'null' => 'NOT NULL',
+ 'length' => '',
+ 'default' => '',
+ 'local' => '',
+ } ),
+ DBIx::DBSchema::Column->new( {
+ 'name' => 'history_date',
+ 'type' => 'int',
+ 'null' => 'NULL',
+ 'length' => '',
+ 'default' => '',
+ 'local' => '',
+ } ),
+ DBIx::DBSchema::Column->new( {
+ 'name' => 'history_user',
+ 'type' => 'varchar',
+ 'null' => 'NOT NULL',
+ 'length' => '80',
+ 'default' => '',
+ 'local' => '',
+ } ),
+ DBIx::DBSchema::Column->new( {
+ 'name' => 'history_action',
+ 'type' => 'varchar',
+ 'null' => 'NOT NULL',
+ 'length' => '80',
+ 'default' => '',
+ 'local' => '',
+ } ),
+ map {
+ my $column = $tableobj->column($_);
+
+ #clone so as to not disturb the original
+ $column = DBIx::DBSchema::Column->new( {
+ map { $_ => $column->$_() }
+ qw( name type null length default local )
+ } );
+
+ $column->type('int')
+ if $column->type eq 'serial';
+ #$column->default('')
+ # if $column->default =~ /^nextval\(/i;
+ #( my $local = $column->local ) =~ s/AUTO_INCREMENT//i;
+ #$column->local($local);
+ $column;
+ } $tableobj->columns
+ ],
+ } );
+ $dbdef->addtable($h_tableobj);
+}
#important
$dbdef->save($dbdef_file);
-&FS::Schema::reload_dbdef($dbdef_file);
+&FS::Record::reload_dbdef($dbdef_file);
###
# create 'em
###
-my $dbh = adminsuidsetup $user;
+my($dbh)=adminsuidsetup $user;
#create tables
$|=1;
@@ -98,12 +232,6 @@ foreach my $statement ( $dbdef->sql($dbh) ) {
or die "CREATE error: ". $dbh->errstr. "\ndoing statement: $statement";
}
-#now go back and reverse engineer the db
-#so we pick up the correct column DEFAULTs for #oidless inserts
-dbdef_create($dbh, $dbdef_file);
-delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
-reload_dbdef($dbdef_file);
-
#cust_main_county
foreach my $country ( sort map uc($_), all_country_codes ) {
@@ -168,15 +296,923 @@ $dbh->disconnect or die $dbh->errstr;
#print "Freeside database initialized sucessfully\n";
-sub dbdef_create { # reverse engineer the schema from the DB and save to file
- my( $dbh, $file ) = @_;
- my $dbdef = new_native DBIx::DBSchema $dbh;
- $dbdef->save($file);
-}
-
sub usage {
- die "Usage:\n freeside-setup user\n";
+ die "Usage:\n freeside-setup [ -s ] user\n";
}
-1;
+###
+# Now it becomes an object. much better.
+###
+sub tables_hash_hack {
+
+ #note that s/(date|change)/_$1/; to avoid keyword conflict.
+ #put a kludge in FS::Record to catch this or? (pry need some date-handling
+ #stuff anyway also)
+
+ my(%tables)=( #yech.}
+
+ 'agent' => {
+ 'columns' => [
+ 'agentnum', 'serial', '', '',
+ 'agent', 'varchar', '', $char_d,
+ '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'], ['disabled'] ],
+ },
+
+ 'agent_type' => {
+ 'columns' => [
+ 'typenum', 'serial', '', '',
+ 'atype', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'typenum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'type_pkgs' => {
+ 'columns' => [
+ 'typenum', 'int', '', '',
+ 'pkgpart', 'int', '', '',
+ ],
+ 'primary_key' => '',
+ 'unique' => [ ['typenum', 'pkgpart'] ],
+ 'index' => [ ['typenum'] ],
+ },
+
+ 'cust_bill' => {
+ 'columns' => [
+ 'invnum', 'serial', '', '',
+ 'custnum', 'int', '', '',
+ '_date', @date_type,
+ 'charged', @money_type,
+ 'printed', 'int', '', '',
+ 'closed', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'invnum',
+ 'unique' => [],
+ 'index' => [ ['custnum'], ['_date'] ],
+ },
+
+ 'cust_bill_event' => {
+ 'columns' => [
+ 'eventnum', 'serial', '', '',
+ 'invnum', 'int', '', '',
+ 'eventpart', 'int', '', '',
+ '_date', @date_type,
+ 'status', 'varchar', '', $char_d,
+ 'statustext', 'text', 'NULL', '',
+ ],
+ 'primary_key' => 'eventnum',
+ #no... there are retries now #'unique' => [ [ 'eventpart', 'invnum' ] ],
+ 'unique' => [],
+ 'index' => [ ['invnum'], ['status'] ],
+ },
+
+ 'part_bill_event' => {
+ 'columns' => [
+ 'eventpart', 'serial', '', '',
+ 'payby', 'char', '', 4,
+ 'event', 'varchar', '', $char_d,
+ 'eventcode', @perl_type,
+ 'seconds', 'int', 'NULL', '',
+ 'weight', 'int', '', '',
+ 'plan', 'varchar', 'NULL', $char_d,
+ 'plandata', 'text', 'NULL', '',
+ 'disabled', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'eventpart',
+ 'unique' => [],
+ 'index' => [ ['payby'], ['disabled'], ],
+ },
+
+ 'cust_bill_pkg' => {
+ 'columns' => [
+ 'pkgnum', 'int', '', '',
+ 'invnum', 'int', '', '',
+ 'setup', @money_type,
+ 'recur', @money_type,
+ 'sdate', @date_type,
+ 'edate', @date_type,
+ 'itemdesc', 'varchar', 'NULL', $char_d,
+ ],
+ 'primary_key' => '',
+ 'unique' => [],
+ 'index' => [ ['invnum'] ],
+ },
+
+ 'cust_bill_pkg_detail' => {
+ 'columns' => [
+ 'detailnum', 'serial', '', '',
+ 'pkgnum', 'int', '', '',
+ 'invnum', 'int', '', '',
+ 'detail', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'detailnum',
+ 'unique' => [],
+ 'index' => [ [ 'pkgnum', 'invnum' ] ],
+ },
+
+ 'cust_credit' => {
+ 'columns' => [
+ 'crednum', 'serial', '', '',
+ 'custnum', 'int', '', '',
+ '_date', @date_type,
+ 'amount', @money_type,
+ 'otaker', 'varchar', '', 32,
+ 'reason', 'text', 'NULL', '',
+ 'closed', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'crednum',
+ 'unique' => [],
+ 'index' => [ ['custnum'] ],
+ },
+
+ 'cust_credit_bill' => {
+ 'columns' => [
+ 'creditbillnum', 'serial', '', '',
+ 'crednum', 'int', '', '',
+ 'invnum', 'int', '', '',
+ '_date', @date_type,
+ 'amount', @money_type,
+ ],
+ 'primary_key' => 'creditbillnum',
+ 'unique' => [],
+ 'index' => [ ['crednum'], ['invnum'] ],
+ },
+
+ 'cust_main' => {
+ 'columns' => [
+ 'custnum', 'serial', '', '',
+ 'agentnum', 'int', '', '',
+# 'titlenum', 'int', 'NULL', '',
+ 'last', 'varchar', '', $char_d,
+# 'middle', 'varchar', 'NULL', $char_d,
+ 'first', 'varchar', '', $char_d,
+ 'ss', 'varchar', 'NULL', 11,
+ 'company', 'varchar', 'NULL', $char_d,
+ 'address1', 'varchar', '', $char_d,
+ 'address2', 'varchar', 'NULL', $char_d,
+ 'city', 'varchar', '', $char_d,
+ 'county', 'varchar', 'NULL', $char_d,
+ 'state', 'varchar', 'NULL', $char_d,
+ 'zip', 'varchar', 'NULL', 10,
+ 'country', 'char', '', 2,
+ 'daytime', 'varchar', 'NULL', 20,
+ 'night', 'varchar', 'NULL', 20,
+ 'fax', 'varchar', 'NULL', 12,
+ 'ship_last', 'varchar', 'NULL', $char_d,
+# 'ship_middle', 'varchar', 'NULL', $char_d,
+ 'ship_first', 'varchar', 'NULL', $char_d,
+ 'ship_company', 'varchar', 'NULL', $char_d,
+ 'ship_address1', 'varchar', 'NULL', $char_d,
+ 'ship_address2', 'varchar', 'NULL', $char_d,
+ 'ship_city', 'varchar', 'NULL', $char_d,
+ 'ship_county', 'varchar', 'NULL', $char_d,
+ 'ship_state', 'varchar', 'NULL', $char_d,
+ 'ship_zip', 'varchar', 'NULL', 10,
+ 'ship_country', 'char', 'NULL', 2,
+ 'ship_daytime', 'varchar', 'NULL', 20,
+ 'ship_night', 'varchar', 'NULL', 20,
+ '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,
+ 'tax', 'char', 'NULL', 1,
+ 'otaker', 'varchar', '', 32,
+ 'refnum', 'int', '', '',
+ 'referral_custnum', 'int', 'NULL', '',
+ 'comments', 'text', 'NULL', '',
+ ],
+ 'primary_key' => 'custnum',
+ 'unique' => [],
+ #'index' => [ ['last'], ['company'] ],
+ 'index' => [ ['last'], [ 'company' ], [ 'referral_custnum' ],
+ [ 'daytime' ], [ 'night' ], [ 'fax' ], [ 'refnum' ],
+ ],
+ },
+
+ 'cust_main_invoice' => {
+ 'columns' => [
+ 'destnum', 'serial', '', '',
+ 'custnum', 'int', '', '',
+ 'dest', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'destnum',
+ 'unique' => [],
+ 'index' => [ ['custnum'], ],
+ },
+
+ 'cust_main_county' => { #county+state+country are checked off the
+ #cust_main_county for validation and to provide
+ # a tax rate.
+ 'columns' => [
+ 'taxnum', 'serial', '', '',
+ 'state', 'varchar', 'NULL', $char_d,
+ 'county', 'varchar', 'NULL', $char_d,
+ 'country', 'char', '', 2,
+ 'taxclass', 'varchar', 'NULL', $char_d,
+ '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' => [],
+ # 'unique' => [ ['taxnum'], ['state', 'county'] ],
+ 'index' => [],
+ },
+
+ 'cust_pay' => {
+ 'columns' => [
+ 'paynum', 'serial', '', '',
+ #now cust_bill_pay #'invnum', 'int', '', '',
+ 'custnum', 'int', '', '',
+ 'paid', @money_type,
+ '_date', @date_type,
+ 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index into
+ # payment type table.
+ 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above
+ 'paybatch', 'varchar', 'NULL', $char_d, #for auditing purposes.
+ 'closed', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'paynum',
+ 'unique' => [],
+ 'index' => [ [ 'custnum' ], [ 'paybatch' ], [ 'payby' ], [ '_date' ] ],
+ },
+
+ 'cust_pay_void' => {
+ 'columns' => [
+ 'paynum', 'int', '', '',
+ 'custnum', 'int', '', '',
+ 'paid', @money_type,
+ '_date', @date_type,
+ 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index into
+ # payment type table.
+ 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above
+ 'paybatch', 'varchar', 'NULL', $char_d, #for auditing purposes.
+ 'closed', 'char', 'NULL', 1,
+ 'void_date', @date_type,
+ 'reason', 'varchar', 'NULL', $char_d,
+ 'otaker', 'varchar', '', 32,
+ ],
+ 'primary_key' => 'paynum',
+ 'unique' => [],
+ 'index' => [ [ 'custnum' ] ],
+ },
+
+ 'cust_bill_pay' => {
+ 'columns' => [
+ 'billpaynum', 'serial', '', '',
+ 'invnum', 'int', '', '',
+ 'paynum', 'int', '', '',
+ 'amount', @money_type,
+ '_date', @date_type
+ ],
+ 'primary_key' => 'billpaynum',
+ 'unique' => [],
+ 'index' => [ [ 'paynum' ], [ 'invnum' ] ],
+ },
+
+ 'cust_pay_batch' => { #what's this used for again? list of customers
+ #in current CARD batch? (necessarily CARD?)
+ 'columns' => [
+ 'paybatchnum', 'serial', '', '',
+ 'invnum', 'int', '', '',
+ 'custnum', 'int', '', '',
+ 'last', 'varchar', '', $char_d,
+ 'first', 'varchar', '', $char_d,
+ 'address1', 'varchar', '', $char_d,
+ 'address2', 'varchar', 'NULL', $char_d,
+ 'city', 'varchar', '', $char_d,
+ 'state', 'varchar', 'NULL', $char_d,
+ 'zip', 'varchar', 'NULL', 10,
+ 'country', 'char', '', 2,
+# 'trancode', 'int', '', '',
+ 'cardnum', 'varchar', '', 16,
+ #'exp', @date_type,
+ 'exp', 'varchar', '', 11,
+ 'payname', 'varchar', 'NULL', $char_d,
+ 'amount', @money_type,
+ ],
+ 'primary_key' => 'paybatchnum',
+ 'unique' => [],
+ 'index' => [ ['invnum'], ['custnum'] ],
+ },
+
+ 'cust_pkg' => {
+ 'columns' => [
+ 'pkgnum', 'serial', '', '',
+ 'custnum', 'int', '', '',
+ 'pkgpart', 'int', '', '',
+ 'otaker', 'varchar', '', 32,
+ 'setup', @date_type,
+ 'bill', @date_type,
+ 'last_bill', @date_type,
+ 'susp', @date_type,
+ 'cancel', @date_type,
+ 'expire', @date_type,
+ 'manual_flag', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'pkgnum',
+ 'unique' => [],
+ 'index' => [ ['custnum'] ],
+ },
+
+ 'cust_refund' => {
+ 'columns' => [
+ 'refundnum', 'serial', '', '',
+ #now cust_credit_refund #'crednum', 'int', '', '',
+ 'custnum', 'int', '', '',
+ '_date', @date_type,
+ 'refund', @money_type,
+ 'otaker', 'varchar', '', 32,
+ 'reason', 'varchar', '', $char_d,
+ 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index
+ # into payment type table.
+ 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above
+ 'paybatch', 'varchar', 'NULL', $char_d,
+ 'closed', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'refundnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'cust_credit_refund' => {
+ 'columns' => [
+ 'creditrefundnum', 'serial', '', '',
+ 'crednum', 'int', '', '',
+ 'refundnum', 'int', '', '',
+ 'amount', @money_type,
+ '_date', @date_type
+ ],
+ 'primary_key' => 'creditrefundnum',
+ 'unique' => [],
+ 'index' => [ [ 'crednum', 'refundnum' ] ],
+ },
+
+
+ 'cust_svc' => {
+ 'columns' => [
+ 'svcnum', 'serial', '', '',
+ 'pkgnum', 'int', 'NULL', '',
+ 'svcpart', 'int', '', '',
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [],
+ 'index' => [ ['svcnum'], ['pkgnum'], ['svcpart'] ],
+ },
+
+ 'part_pkg' => {
+ 'columns' => [
+ 'pkgpart', 'serial', '', '',
+ 'pkg', 'varchar', '', $char_d,
+ 'comment', 'varchar', '', $char_d,
+ 'promo_code', 'varchar', 'NULL', $char_d,
+ 'setup', @perl_type,
+ 'freq', 'varchar', '', $char_d, #billing frequency
+ 'recur', @perl_type,
+ 'setuptax', 'char', 'NULL', 1,
+ 'recurtax', 'char', 'NULL', 1,
+ 'plan', 'varchar', 'NULL', $char_d,
+ 'plandata', 'text', 'NULL', '',
+ 'disabled', 'char', 'NULL', 1,
+ 'taxclass', 'varchar', 'NULL', $char_d,
+ ],
+ 'primary_key' => 'pkgpart',
+ 'unique' => [],
+ 'index' => [ [ 'promo_code' ], [ 'disabled' ] ],
+ },
+
+# 'part_title' => {
+# 'columns' => [
+# 'titlenum', 'int', '', '',
+# 'title', 'varchar', '', $char_d,
+# ],
+# 'primary_key' => 'titlenum',
+# 'unique' => [ [] ],
+# 'index' => [ [] ],
+# },
+
+ 'pkg_svc' => {
+ 'columns' => [
+ 'pkgpart', 'int', '', '',
+ 'svcpart', 'int', '', '',
+ 'quantity', 'int', '', '',
+ 'primary_svc','char', 'NULL', 1,
+ ],
+ 'primary_key' => '',
+ 'unique' => [ ['pkgpart', 'svcpart'] ],
+ 'index' => [ ['pkgpart'] ],
+ },
+
+ 'part_referral' => {
+ 'columns' => [
+ 'refnum', 'serial', '', '',
+ 'referral', 'varchar', '', $char_d,
+ 'disabled', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'refnum',
+ 'unique' => [],
+ 'index' => [ ['disabled'] ],
+ },
+
+ 'part_svc' => {
+ 'columns' => [
+ 'svcpart', 'serial', '', '',
+ 'svc', 'varchar', '', $char_d,
+ 'svcdb', 'varchar', '', $char_d,
+ 'disabled', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'svcpart',
+ 'unique' => [],
+ 'index' => [ [ 'disabled' ] ],
+ },
+
+ 'part_svc_column' => {
+ 'columns' => [
+ 'columnnum', 'serial', '', '',
+ 'svcpart', 'int', '', '',
+ 'columnname', 'varchar', '', 64,
+ 'columnvalue', 'varchar', 'NULL', $char_d,
+ 'columnflag', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'columnnum',
+ 'unique' => [ [ 'svcpart', 'columnname' ] ],
+ 'index' => [ [ 'svcpart' ] ],
+ },
+
+ #(this should be renamed to part_pop)
+ 'svc_acct_pop' => {
+ 'columns' => [
+ 'popnum', 'serial', '', '',
+ 'city', 'varchar', '', $char_d,
+ 'state', 'varchar', '', $char_d,
+ 'ac', 'char', '', 3,
+ 'exch', 'char', '', 3,
+ 'loc', 'char', 'NULL', 4, #NULL for legacy purposes
+ ],
+ 'primary_key' => 'popnum',
+ 'unique' => [],
+ 'index' => [ [ 'state' ] ],
+ },
+
+ 'part_pop_local' => {
+ 'columns' => [
+ 'localnum', 'serial', '', '',
+ 'popnum', 'int', '', '',
+ 'city', 'varchar', 'NULL', $char_d,
+ 'state', 'char', 'NULL', 2,
+ 'npa', 'char', '', 3,
+ 'nxx', 'char', '', 3,
+ ],
+ 'primary_key' => 'localnum',
+ 'unique' => [],
+ 'index' => [ [ 'npa', 'nxx' ], [ 'popnum' ] ],
+ },
+
+ 'svc_acct' => {
+ 'columns' => [
+ 'svcnum', 'int', '', '',
+ 'username', 'varchar', '', $username_len, #unique (& remove dup code)
+ '_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', '',
+ 'gid', 'int', 'NULL', '',
+ 'finger', 'varchar', 'NULL', $char_d,
+ 'dir', 'varchar', 'NULL', $char_d,
+ 'shell', 'varchar', 'NULL', $char_d,
+ 'quota', 'varchar', 'NULL', $char_d,
+ 'slipip', 'varchar', 'NULL', 15, #four TINYINTs, bah.
+ 'seconds', 'int', 'NULL', '', #uhhhh
+ 'domsvc', 'int', '', '',
+ ],
+ 'primary_key' => 'svcnum',
+ #'unique' => [ [ 'username', 'domsvc' ] ],
+ 'unique' => [],
+ 'index' => [ ['username'], ['domsvc'] ],
+ },
+
+ #'svc_charge' => {
+ # 'columns' => [
+ # 'svcnum', 'int', '', '',
+ # 'amount', @money_type,
+ # ],
+ # 'primary_key' => 'svcnum',
+ # 'unique' => [ [] ],
+ # 'index' => [ [] ],
+ #},
+
+ 'svc_domain' => {
+ 'columns' => [
+ 'svcnum', 'int', '', '',
+ 'domain', 'varchar', '', $char_d,
+ 'catchall', 'int', 'NULL', '',
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [ ['domain'] ],
+ 'index' => [],
+ },
+
+ 'domain_record' => {
+ 'columns' => [
+ 'recnum', 'serial', '', '',
+ 'svcnum', 'int', '', '',
+ #'reczone', 'varchar', '', $char_d,
+ 'reczone', 'varchar', '', 255,
+ 'recaf', 'char', '', 2,
+ 'rectype', 'varchar', '', 5,
+ #'recdata', 'varchar', '', $char_d,
+ 'recdata', 'varchar', '', 255,
+ ],
+ 'primary_key' => 'recnum',
+ 'unique' => [],
+ 'index' => [ ['svcnum'] ],
+ },
+
+ 'svc_forward' => {
+ 'columns' => [
+ 'svcnum', 'int', '', '',
+ 'srcsvc', 'int', 'NULL', '',
+ 'src', 'varchar', 'NULL', 255,
+ 'dstsvc', 'int', 'NULL', '',
+ 'dst', 'varchar', 'NULL', 255,
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [],
+ 'index' => [ ['srcsvc'], ['dstsvc'] ],
+ },
+
+ 'svc_www' => {
+ 'columns' => [
+ 'svcnum', 'int', '', '',
+ 'recnum', 'int', '', '',
+ 'usersvc', 'int', '', '',
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ #'svc_wo' => {
+ # 'columns' => [
+ # 'svcnum', 'int', '', '',
+ # 'svcnum', 'int', '', '',
+ # 'svcnum', 'int', '', '',
+ # 'worker', 'varchar', '', $char_d,
+ # '_date', @date_type,
+ # ],
+ # 'primary_key' => 'svcnum',
+ # 'unique' => [ [] ],
+ # 'index' => [ [] ],
+ #},
+
+ 'prepay_credit' => {
+ 'columns' => [
+ 'prepaynum', 'serial', '', '',
+ 'identifier', 'varchar', '', $char_d,
+ 'amount', @money_type,
+ 'seconds', 'int', 'NULL', '',
+ ],
+ 'primary_key' => 'prepaynum',
+ 'unique' => [ ['identifier'] ],
+ 'index' => [],
+ },
+
+ 'port' => {
+ 'columns' => [
+ 'portnum', 'serial', '', '',
+ 'ip', 'varchar', 'NULL', 15,
+ 'nasport', 'int', 'NULL', '',
+ 'nasnum', 'int', '', '',
+ ],
+ 'primary_key' => 'portnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'nas' => {
+ 'columns' => [
+ 'nasnum', 'serial', '', '',
+ 'nas', 'varchar', '', $char_d,
+ 'nasip', 'varchar', '', 15,
+ 'nasfqdn', 'varchar', '', $char_d,
+ 'last', 'int', '', '',
+ ],
+ 'primary_key' => 'nasnum',
+ 'unique' => [ [ 'nas' ], [ 'nasip' ] ],
+ 'index' => [ [ 'last' ] ],
+ },
+
+ 'session' => {
+ 'columns' => [
+ 'sessionnum', 'serial', '', '',
+ 'portnum', 'int', '', '',
+ 'svcnum', 'int', '', '',
+ 'login', @date_type,
+ 'logout', @date_type,
+ ],
+ 'primary_key' => 'sessionnum',
+ 'unique' => [],
+ 'index' => [ [ 'portnum' ] ],
+ },
+
+ 'queue' => {
+ 'columns' => [
+ 'jobnum', 'serial', '', '',
+ 'job', 'text', '', '',
+ '_date', 'int', '', '',
+ 'status', 'varchar', '', $char_d,
+ 'statustext', 'text', 'NULL', '',
+ 'svcnum', 'int', 'NULL', '',
+ ],
+ 'primary_key' => 'jobnum',
+ 'unique' => [],
+ 'index' => [ [ 'svcnum' ], [ 'status' ] ],
+ },
+
+ 'queue_arg' => {
+ 'columns' => [
+ 'argnum', 'serial', '', '',
+ 'jobnum', 'int', '', '',
+ 'arg', 'text', 'NULL', '',
+ ],
+ 'primary_key' => 'argnum',
+ 'unique' => [],
+ 'index' => [ [ 'jobnum' ] ],
+ },
+
+ 'queue_depend' => {
+ 'columns' => [
+ 'dependnum', 'serial', '', '',
+ 'jobnum', 'int', '', '',
+ 'depend_jobnum', 'int', '', '',
+ ],
+ 'primary_key' => 'dependnum',
+ 'unique' => [],
+ 'index' => [ [ 'jobnum' ], [ 'depend_jobnum' ] ],
+ },
+
+ 'export_svc' => {
+ 'columns' => [
+ 'exportsvcnum' => 'serial', '', '',
+ 'exportnum' => 'int', '', '',
+ 'svcpart' => 'int', '', '',
+ ],
+ 'primary_key' => 'exportsvcnum',
+ 'unique' => [ [ 'exportnum', 'svcpart' ] ],
+ 'index' => [ [ 'exportnum' ], [ 'svcpart' ] ],
+ },
+
+ 'part_export' => {
+ 'columns' => [
+ 'exportnum', 'serial', '', '',
+ #'svcpart', 'int', '', '',
+ 'machine', 'varchar', '', $char_d,
+ 'exporttype', 'varchar', '', $char_d,
+ 'nodomain', 'char', 'NULL', 1,
+ ],
+ 'primary_key' => 'exportnum',
+ 'unique' => [],
+ 'index' => [ [ 'machine' ], [ 'exporttype' ] ],
+ },
+
+ 'part_export_option' => {
+ 'columns' => [
+ 'optionnum', 'serial', '', '',
+ 'exportnum', 'int', '', '',
+ 'optionname', 'varchar', '', $char_d,
+ 'optionvalue', 'text', 'NULL', '',
+ ],
+ 'primary_key' => 'optionnum',
+ 'unique' => [],
+ 'index' => [ [ 'exportnum' ], [ 'optionname' ] ],
+ },
+
+ 'radius_usergroup' => {
+ 'columns' => [
+ 'usergroupnum', 'serial', '', '',
+ 'svcnum', 'int', '', '',
+ 'groupname', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'usergroupnum',
+ 'unique' => [],
+ 'index' => [ [ 'svcnum' ], [ 'groupname' ] ],
+ },
+
+ 'msgcat' => {
+ 'columns' => [
+ 'msgnum', 'serial', '', '',
+ 'msgcode', 'varchar', '', $char_d,
+ 'locale', 'varchar', '', 16,
+ 'msg', 'text', '', '',
+ ],
+ 'primary_key' => 'msgnum',
+ 'unique' => [ [ 'msgcode', 'locale' ] ],
+ 'index' => [],
+ },
+
+ 'cust_tax_exempt' => {
+ 'columns' => [
+ 'exemptnum', 'serial', '', '',
+ 'custnum', 'int', '', '',
+ 'taxnum', 'int', '', '',
+ 'year', 'int', '', '',
+ 'month', 'int', '', '',
+ 'amount', @money_type,
+ ],
+ 'primary_key' => 'exemptnum',
+ 'unique' => [ [ 'custnum', 'taxnum', 'year', 'month' ] ],
+ 'index' => [],
+ },
+
+ 'router' => {
+ 'columns' => [
+ 'routernum', 'serial', '', '',
+ 'routername', 'varchar', '', $char_d,
+ 'svcnum', 'int', 'NULL', '',
+ ],
+ 'primary_key' => 'routernum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'part_svc_router' => {
+ 'columns' => [
+ 'svcpart', 'int', '', '',
+ 'routernum', 'int', '', '',
+ ],
+ 'primary_key' => '',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'addr_block' => {
+ 'columns' => [
+ 'blocknum', 'serial', '', '',
+ 'routernum', 'int', '', '',
+ 'ip_gateway', 'varchar', '', 15,
+ 'ip_netmask', 'int', '', '',
+ ],
+ 'primary_key' => 'blocknum',
+ 'unique' => [ [ 'blocknum', 'routernum' ] ],
+ 'index' => [],
+ },
+
+ 'svc_broadband' => {
+ 'columns' => [
+ 'svcnum', 'int', '', '',
+ 'blocknum', 'int', '', '',
+ 'speed_up', 'int', '', '',
+ 'speed_down', 'int', '', '',
+ 'ip_addr', 'varchar', '', 15,
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'part_virtual_field' => {
+ 'columns' => [
+ 'vfieldpart', 'int', '', '',
+ 'dbtable', 'varchar', '', 32,
+ 'name', 'varchar', '', 32,
+ 'check_block', 'text', 'NULL', '',
+ 'length', 'int', 'NULL', '',
+ 'list_source', 'text', 'NULL', '',
+ 'label', 'varchar', 'NULL', 80,
+ ],
+ 'primary_key' => 'vfieldpart',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'virtual_field' => {
+ 'columns' => [
+ 'recnum', 'int', '', '',
+ 'vfieldpart', 'int', '', '',
+ 'value', 'varchar', '', 128,
+ ],
+ 'primary_key' => '',
+ 'unique' => [ [ 'vfieldpart', 'recnum' ] ],
+ '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', 'NULL', '',
+ 'title', 'varchar', 'NULL', $char_d,
+ ],
+ 'primary_key' => 'svcnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'cust_pay_refund' => {
+ 'columns' => [
+ 'payrefundnum', 'serial', '', '',
+ 'paynum', 'int', '', '',
+ 'refundnum', 'int', '', '',
+ '_date', @date_type,
+ 'amount', @money_type,
+ ],
+ 'primary_key' => 'payrefundnum',
+ 'unique' => [],
+ 'index' => [ ['paynum'], ['refundnum'] ],
+ },
+
+ 'part_pkg_option' => {
+ 'columns' => [
+ 'optionnum', 'serial', '', '',
+ 'pkgpart', 'int', '', '',
+ 'optionname', 'varchar', '', $char_d,
+ 'optionvalue', 'text', 'NULL', '',
+ ],
+ 'primary_key' => 'optionnum',
+ 'unique' => [],
+ 'index' => [ [ 'pkgpart' ], [ 'optionname' ] ],
+ },
+
+ 'rate' => {
+ 'columns' => [
+ 'ratenum', 'serial', '', '',
+ 'ratename', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'ratenum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'rate_detail' => {
+ 'columns' => [
+ 'ratenum', 'int', '', '',
+ 'orig_regionnum', 'int', 'NULL', '',
+ 'dest_regionnum', 'int', '', '',
+ 'min_included', 'int', '', '',
+ 'min_charge', @money_type,
+ 'sec_granularity', 'int', '', '',
+ #time period (link to table of periods)?
+ ],
+ 'primary_key' => '',
+ 'unique' => [ [ 'ratenum', 'orig_regionnum', 'dest_regionnum' ] ],
+ 'index' => [],
+ },
+
+ 'rate_region' => {
+ 'columns' => [
+ 'regionnum', 'serial', '', '',
+ 'regionname', 'varchar', '', $char_d,
+ ],
+ 'primary_key' => 'regionnum',
+ 'unique' => [],
+ 'index' => [],
+ },
+
+ 'rate_prefix' => {
+ 'columns' => [
+ 'prefixnum', 'serial', '', '',
+ 'regionnum', 'int', '', '',,
+ 'countrycode', 'varchar', '', 3,
+ 'npa', 'varchar', 'NULL', 6,
+ 'nxx', 'varchar', 'NULL', 3,
+ ],
+ 'primary_key' => 'prefixnum',
+ 'unique' => [],
+ 'index' => [ [ 'countrycode' ], [ 'regionnum' ] ],
+ },
+
+
+ );
+
+ %tables;
+
+}
diff --git a/FS/bin/freeside-sqlradius-radacctd b/FS/bin/freeside-sqlradius-radacctd
index e98eaa015..4e8d57c51 100644
--- a/FS/bin/freeside-sqlradius-radacctd
+++ b/FS/bin/freeside-sqlradius-radacctd
@@ -1,122 +1,159 @@
-#!/usr/bin/perl -w
+#!/usr/bin/perl -Tw
use strict;
-use vars qw( @part_export );
-use subs qw(myshutdown);
-use POSIX qw(:sys_wait_h);
-#use IO::File;
-use FS::Daemon qw(daemonize1 drop_root logfile daemonize2 sigint sigterm);
-use FS::UID qw(adminsuidsetup); #forksuidsetup driver_name dbh myconnect);
-use FS::Record qw(qsearch); # qsearchs);
-use FS::part_export;
+use vars qw( $log_file $sigterm $sigint );
+use subs qw( _die _logmsg );
+use Fcntl qw(:flock);
+use POSIX qw(setsid);
+use Date::Format;
+use IO::File;
+use FS::UID qw(adminsuidsetup);
+#use FS::Record qw(qsearch qsearchs);
+#use FS::part_export;
#use FS::svc_acct;
#use FS::cust_svc;
+#lots of false laziness w/freeside-queued
+
my $user = shift or die &usage;
-#daemonize1('freeside-sqlradius-radacctd', $user); #keep unique pid files w/multi installs
-daemonize1('freeside-sqlradius-radacctd');
+#my $pid_file = "/var/run/freeside-sqlradius-radacctd.$user.pid";
+my $pid_file = "/var/run/freeside-sqlradius-radacctd.pid";
-drop_root();
+&daemonize1;
-#$ENV{HOME} = (getpwuid($>))[7]; #for ssh
+#sub REAPER { my $pid = wait; $SIG{CHLD} = \&REAPER; $kids--; }
+#$SIG{CHLD} = \&REAPER;
-adminsuidsetup $user;
+$sigterm = 0;
+$sigint = 0;
+$SIG{INT} = sub { warn "SIGINT received; shutting down\n"; $sigint++; };
+$SIG{TERM} = sub { warn "SIGTERM received; shutting down\n"; $sigterm++; };
-logfile( "/usr/local/etc/freeside/sqlradius-radacctd-log.". $FS::UID::datasrc );
+my $freeside_gid = scalar(getgrnam('freeside'))
+ or die "can't setgid to freeside group\n";
+$) = $freeside_gid;
+$( = $freeside_gid;
+#if freebsd can't setuid(), presumably it can't setgid() either. grr fleabsd
+($(,$)) = ($),$();
+$) = $freeside_gid;
-daemonize2();
+$> = $FS::UID::freeside_uid;
+$< = $FS::UID::freeside_uid;
+#freebsd is sofa king broken, won't setuid()
+($<,$>) = ($>,$<);
+$> = $FS::UID::freeside_uid;
-#--
+#$ENV{HOME} = (getpwuid($>))[7]; #for ssh
+adminsuidsetup $user;
-#don't just look for ->can('usage_sessions'), we're sqlradius-specific
-# (radiator is supposed to be setup with a radacct table)
+$log_file= "/usr/local/etc/freeside/sqlradius-radacctd-log.". $FS::UID::datasrc;
-@part_export =
- qsearch('part_export', { 'exporttype' => 'sqlradius' } );
-push @part_export,
- qsearch('part_export', { 'exporttype' => 'sqlradius_withdomain' } );
-push @part_export,
- qsearch('part_export', { 'exporttype' => 'radiator' } );
+&daemonize2;
-@part_export = grep { ! $_->option('ignore_accounting') } @part_export;
+$SIG{__DIE__} = \&_die;
+$SIG{__WARN__} = \&_logmsg;
-die "no sqlradius, sqlradius_withdomain or radiator exports without".
- " ignore_accounting"
- unless @part_export;
+warn "freeside-sqlradius-radacctd starting\n";
+
+#eslaf
+
+#my $machine = shift or die &usage; #would need to be up higher for real
+my @exports = qsearch('part_export', { 'exporttype' => 'sqlradius' } );
while (1) {
- #fork off one kid per export (machine)
- # _>{'_radacct_kid'} is an evil kludge
- foreach my $part_export ( grep ! $_->{'_radacct_kid'}, @part_export ) {
-
- defined( my $pid = fork ) or do {
- warn "WARNING: can't fork to spawn child for ". $part_export->machine;
+ my %seen = ();
+ foreach my $export ( @exports ) {
+ next if $seen{$export->option('datasrc')}++;
+ my $dbh = DBI->connect(
+ map { $export->option($_) } qw( datasrc username password )
+ ) or do {
+ warn "can't connect to ". $export->option('datasrc'). ": ". $DBI::errstr;
next;
- };
-
- if ( $pid ) {
- $part_export->{'_radacct_kid'} = $pid;
- warn "child $pid spawned for ". $part_export->machine;
- } else { #kid time
+ }
- adminsuidsetup($user); #get our own db handle
+ # find old radacct position
+ #$lastid = 0;
- until ( sigint || sigterm ) {
- $part_export->update_svc_acct();
- sleep 1;
- }
+ # get new radacct records
+ my $sth = $dbh->prepare('SELECT * FROM radacct WHERE radacctid > ?') or do {
+ warn "can't select in radacct table from ". $export->option('datasrc').
+ ": ". $dbh->errstr;
+ next;
+ };
- warn "child for ". $part_export->machine. " done";
- exit;
+ while ( my $radacct = $sth->fetchrow_arrayref({}) ) {
- } #eo kid
+ my $session = new FS::session {
+ portnum =>
+ svcnum =>
+ login =>
+ #logout =>
+ };
- }
+ }
- #reap up any kids that died...
- &reap_kids;
+ # look for updated radacct records & replace them
- myshutdown() if sigterm() || sigint();
+ }
sleep 5;
+
}
-#--
+#more false laziness w/freeside-queued
-sub myshutdown {
- &reap_kids;
+sub usage {
+ die "Usage:\n\n freeside-sqlradius-radacctd user\n";
+}
- #kill all the kids
- kill 'TERM', $_ foreach grep $_, map $_->{'_radacct_kid'}, @part_export;
+sub _die {
+ my $msg = shift;
+ unlink $pid_file if -e $pid_file;
+ _logmsg($msg);
+}
- my $wait = 12; #wait up to 1 minute
- while ( ( grep $_->{'_radacct_kid'}, @part_export ) && $wait-- ) {
- warn "waiting for children to terminate";
- sleep 5;
- &reap_kids;
- }
- warn "abandoning children" if grep $_->{'_radacct_kid'}, @part_export;
- die "exiting";
+sub _logmsg {
+ chomp( my $msg = shift );
+ my $log = new IO::File ">>$log_file";
+ flock($log, LOCK_EX);
+ seek($log, 0, 2);
+ print $log "[". time2str("%a %b %e %T %Y",time). "] [$$] $msg\n";
+ flock($log, LOCK_UN);
+ close $log;
}
-sub reap_kids {
- #warn "reaping kids\n";
- foreach my $part_export ( grep $_->{'_radacct_kid'}, @part_export ) {
- my $pid = $part_export->{'_radacct_kid'};
- my $kid = waitpid($pid, WNOHANG);
- if ( $kid > 0 ) {
- $part_export->{'_radacct_kid'} = '';
- }
+sub daemonize1 {
+
+ chdir "/" or die "Can't chdir to /: $!";
+ open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
+ defined(my $pid = fork) or die "Can't fork: $!";
+ if ( $pid ) {
+ print "freeside-sqlradius-radacctd started with pid $pid\n";
+ #logging to $log_file\n";
+ exit unless $pid_file;
+ my $pidfh = new IO::File ">$pid_file" or exit;
+ print $pidfh "$pid\n";
+ exit;
}
- #warn "done reaping\n";
+ #open STDOUT, '>/dev/null'
+ # or die "Can't write to /dev/null: $!";
+ #setsid or die "Can't start a new session: $!";
+ #open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
+
}
-sub usage {
- die "Usage:\n\n freeside-sqlradius-radacctd user\n";
+sub daemonize2 {
+ open STDOUT, '>/dev/null'
+ or die "Can't write to /dev/null: $!";
+ setsid or die "Can't start a new session: $!";
+ open STDERR, '>&STDOUT' or die "Can't dup stdout: $!";
}
+
+#eslaf
+
=head1 NAME
freeside-sqlradius-radacctd - Real-time radacct import daemon
@@ -127,24 +164,17 @@ freeside-sqlradius-radacctd - Real-time radacct import daemon
=head1 DESCRIPTION
-Imports records from an the SQL radacct tables of all sqlradius,
-sqlradius_withdomain and radiator exports (except those with the
-ignore_accounting flag) and updates the svc_acct.seconds for each account.
-Runs as a daemon and updates the database in real-time.
-
-B<username> is a username added by freeside-adduser.
-
-=head1 RADIUS DATABASE CHANGES
+Imports records from an SQL radacct table in real-time into the session
+monitor.
-ALTER TABLE radacct ADD COLUMN FreesideStatus varchar(32) NULL;
+This enables per-minute or per-hour charges as well as the
+"View active NAS ports" function.
-If you want to ignore the existing accountg records, also do:
-
-UPDATE radacct SET FreesideStatus = 'done' WHERE FreesideStatus IS NULL;
+B<username> is a username added by freeside-adduser.
=head1 SEE ALSO
-=cut
+session.html from the base documentation.
-1;
+=cut
diff --git a/FS/bin/freeside-sqlradius-reset b/FS/bin/freeside-sqlradius-reset
index 2ac5012d4..11cbe9e36 100755
--- a/FS/bin/freeside-sqlradius-reset
+++ b/FS/bin/freeside-sqlradius-reset
@@ -48,9 +48,6 @@ foreach my $export ( @exports ) {
foreach my $svc_acct ( @svc_acct ) {
- $svc_acct->check; #set any fixed usergroup so it'll export even if all
- #svc_acct records don't have the group yet
-
#false laziness with FS::svc_acct::insert (like it matters)
my $error = $export->export_insert($svc_acct);
die $error if $error;
diff --git a/FS/bin/freeside-upgrade b/FS/bin/freeside-upgrade
deleted file mode 100755
index 419384c2a..000000000
--- a/FS/bin/freeside-upgrade
+++ /dev/null
@@ -1,131 +0,0 @@
-#!/usr/bin/perl -w
-
-use strict;
-use vars qw($DEBUG $DRY_RUN);
-use Term::ReadKey;
-use DBIx::DBSchema 0.27;
-use FS::UID qw(adminsuidsetup checkeuid datasrc ); #getsecrets);
-use FS::Schema qw( dbdef dbdef_dist reload_dbdef );
-
-
-$DEBUG = 1;
-$DRY_RUN = 0;
-
-
-die "Not running uid freeside!" unless checkeuid();
-
-my $user = shift or die &usage;
-my $dbh = adminsuidsetup($user);
-
-#needs to match FS::Schema...
-my $dbdef_file = "/usr/local/etc/freeside/dbdef.". datasrc;
-
-dbdef_create($dbh, $dbdef_file);
-
-delete $FS::Schema::dbdef_cache{$dbdef_file}; #force an actual reload
-reload_dbdef($dbdef_file);
-
-
-foreach my $table ( dbdef_dist->tables ) {
-
- if ( dbdef->table($table) ) {
-
- warn "$table exists\n" if $DEBUG > 1;
-
- foreach my $column ( dbdef_dist->table($table)->columns ) {
- if ( dbdef->table($table)->column($column) ) {
- warn " $table.$column exists\n" if $DEBUG > 2;
- } else {
-
- if ( $DEBUG ) {
- print STDERR "column $table.$column does not exist. create?";
- next unless yesno();
- }
-
- foreach my $statement (
- dbdef_dist->table($table)->column($column)->sql_add_column( $dbh )
- ) {
- warn "$statement\n" if $DEBUG || $DRY_RUN;
- unless ( $DRY_RUN ) {
- $dbh->do( $statement)
- or die "CREATE error: ". $dbh->errstr. "\nexecuting: $statement";
- }
- }
-
- }
-
- }
-
- #should eventually check & create missing indices
-
- #should eventually drop columns not in dbdef_dist...
-
- } else {
-
- if ( $DEBUG ) {
- print STDERR "table $table does not exist. create?";
- next unless yesno();
- }
-
- foreach my $statement (
- dbdef_dist->table($table)->sql_create_table( $dbh )
- ) {
- warn "$statement\n" if $DEBUG || $DRY_RUN;
- unless ( $DRY_RUN ) {
- $dbh->do( $statement)
- or die "CREATE error: ". $dbh->errstr. "\nexecuting: $statement";
- }
- }
-
- }
-
-}
-
-# should eventually drop tables not in dbdef_dist too i guess...
-
-$dbh->commit or die $dbh->errstr;
-
-dbdef_create($dbh, $dbdef_file);
-
-$dbh->disconnect or die $dbh->errstr;
-
-###
-
-my $all = 0;
-sub yesno {
- print STDERR ' [yes/no/all] ';
- if ( $all ) {
- warn "yes\n";
- return 1;
- } else {
- while ( 1 ) {
- ReadMode 4;
- my $x = lc(ReadKey);
- ReadMode 0;
- if ( $x eq 'n' ) {
- warn "no\n";
- return 0;
- } elsif ( $x eq 'y' ) {
- warn "yes\n";
- return 1;
- } elsif ( $x eq 'a' ) {
- warn "yes\n";
- $all = 1;
- return 1;
- }
- }
- }
-}
-
-sub dbdef_create { # reverse engineer the schema from the DB and save to file
- my( $dbh, $file ) = @_;
- my $dbdef = new_native DBIx::DBSchema $dbh;
- $dbdef->save($file);
-}
-
-sub usage {
- die "Usage:\n freeside-upgrade user\n";
-}
-
-1;
-
diff --git a/FS/t/ClientAPI_SessionCache.t b/FS/t/ClientAPI_SessionCache.t
deleted file mode 100644
index 605803eef..000000000
--- a/FS/t/ClientAPI_SessionCache.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::ClientAPI_SessionCache;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/Daemon.t b/FS/t/Daemon.t
deleted file mode 100644
index 24893fd94..000000000
--- a/FS/t/Daemon.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::Daemon;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/agent_payment_gateway.t b/FS/t/agent_payment_gateway.t
deleted file mode 100644
index af78a9a27..000000000
--- a/FS/t/agent_payment_gateway.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::agent_payment_gateway;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/banned_pay.t b/FS/t/banned_pay.t
deleted file mode 100644
index bef1ff25f..000000000
--- a/FS/t/banned_pay.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::banned_pay;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/cancel_reason.t b/FS/t/cancel_reason.t
deleted file mode 100644
index a5948f657..000000000
--- a/FS/t/cancel_reason.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::cancel_reason;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/clientapi_session.t b/FS/t/clientapi_session.t
deleted file mode 100644
index a6414c3d8..000000000
--- a/FS/t/clientapi_session.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::clientapi_session;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/clientapi_session_field.t b/FS/t/clientapi_session_field.t
deleted file mode 100644
index a9d4fa91a..000000000
--- a/FS/t/clientapi_session_field.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::clientapi_session_field;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/cust_main_Mixin.t b/FS/t/cust_main_Mixin.t
deleted file mode 100644
index c8b929117..000000000
--- a/FS/t/cust_main_Mixin.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::cust_main_Mixin;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/h_domain_record.t b/FS/t/h_domain_record.t
deleted file mode 100644
index f48e72e9b..000000000
--- a/FS/t/h_domain_record.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::h_domain_record;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/option_Common.t b/FS/t/option_Common.t
deleted file mode 100644
index ad261415c..000000000
--- a/FS/t/option_Common.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::option_Common;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/part_export-radiator.t b/FS/t/part_export-radiator.t
deleted file mode 100644
index 546e9de30..000000000
--- a/FS/t/part_export-radiator.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::part_export::radiator;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/payment_gateway.t b/FS/t/payment_gateway.t
deleted file mode 100644
index 4bcc78153..000000000
--- a/FS/t/payment_gateway.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::payment_gateway;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/payment_gateway_option.t b/FS/t/payment_gateway_option.t
deleted file mode 100644
index 19e645121..000000000
--- a/FS/t/payment_gateway_option.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::payment_gateway_option;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/reg_code.t b/FS/t/reg_code.t
deleted file mode 100644
index 4b9599078..000000000
--- a/FS/t/reg_code.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::reg_code;
-$loaded=1;
-print "ok 1\n";
diff --git a/FS/t/reg_code_pkg.t b/FS/t/reg_code_pkg.t
deleted file mode 100644
index 7f89ffaee..000000000
--- a/FS/t/reg_code_pkg.t
+++ /dev/null
@@ -1,5 +0,0 @@
-BEGIN { $| = 1; print "1..1\n" }
-END {print "not ok 1\n" unless $loaded;}
-use FS::reg_code_pkg;
-$loaded=1;
-print "ok 1\n";