}
-=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END DATASRC DB_USERNAME DB_PASSWORD
+=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END
Returns the numbers of seconds all accounts (see L<FS::svc_acct>) in this
package have been online between TIMESTAMP_START (inclusive) and TIMESTAMP_END
-(exclusive), according to an external SQL radacct table, such as those
-generated by ICRADIUS or FreeRADIUS. Sessions which started in the specified
-range but are still open are counted from session start to the end of the
-range. Also, sessions which end in the range but started earlier are counted
-from the start of the range to session end. Finally, sessions which start
-before the range but end after (or are still open) are counted for the entire
-range.
+(exclusive).
TIMESTAMP_START and TIMESTAMP_END are specified as UNIX timestamps; see
L<perlfunc/"time">. Also see L<Time::Local> and L<Date::Parse> for conversion
=cut
sub seconds_since_sqlradacct {
- my($self, $start, $end, $datasrc, $db_user, $db_pass) = @_;
-
- my $dbh = DBI->connect($datasrc, $db_user, $db_pass)
- or die "can't connect to $datasrc: ". $DBI::errstr;
+ my($self, $start, $end) = @_;
my $seconds = 0;
foreach my $cust_svc (
grep { $_->part_svc->svcdb eq 'svc_acct' } $self->cust_svc
) {
- $seconds += $cust_svc->seconds_since_sqlradacct($start, $end, $dbh);
+ $seconds += $cust_svc->seconds_since_sqlradacct($start, $end);
}
$seconds;
=head1 VERSION
-$Id: cust_pkg.pm,v 1.26 2002-10-14 06:17:14 ivan Exp $
+$Id: cust_pkg.pm,v 1.27 2002-10-17 14:16:17 ivan Exp $
=head1 BUGS
use FS::svc_domain;
use FS::svc_forward;
use FS::domain_record;
+use FS::part_export;
@ISA = qw( FS::Record );
$sth->fetchrow_arrayref->[0];
}
-=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END ( DBI_DATABASE_HANDLE | DATASRC DB_USERNAME DB_PASSWORD )
+=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END
See L<FS::svc_acct/seconds_since_sqlradacct>. Equivalent to
$cust_svc->svc_x->seconds_since, but more efficient. Meaningless for records
where B<svcdb> is not "svc_acct".
-NOTE: specifying a DATASRC/USERNAME/PASSWORD instead of a DBI database handle
-is not yet implemented.
-
=cut
#note: implementation here, POD in FS::svc_acct
sub seconds_since_sqlradacct {
- my($self, $start, $end, $dbh) = @_;
+ my($self, $start, $end) = @_;
my $username = $self->svc_x->username;
- #select a unix time conversion function based on database type
- my $str2time;
- if ( $dbh->{Driver}->{Name} eq 'mysql' ) {
- $str2time = 'UNIX_TIMESTAMP(';
- } elsif ( $dbh->{Driver}->{Name} eq 'Pg' ) {
- $str2time = 'EXTRACT( EPOCH FROM ';
- } else {
- warn "warning: unknown database type ". $dbh->{Driver}->{Name}.
- "; guessing how to convert to UNIX timestamps";
- $str2time = 'extract(epoch from ';
+ my @part_export = $self->part_svc->part_export('sqlradius')
+ or die "no sqlradius export configured for this service type";
+ #or return undef;
+
+ my $seconds = 0;
+ foreach my $part_export ( @part_export ) {
+
+ my $dbh = DBI->connect( map { $part_export->option($_) }
+ qw(datasrc username password) )
+ or die "can't connect to sqlradius database: ". $DBI::errstr;
+
+ #select a unix time conversion function based on database type
+ my $str2time;
+ if ( $dbh->{Driver}->{Name} eq 'mysql' ) {
+ $str2time = 'UNIX_TIMESTAMP(';
+ } elsif ( $dbh->{Driver}->{Name} eq 'Pg' ) {
+ $str2time = 'EXTRACT( EPOCH FROM ';
+ } else {
+ warn "warning: unknown database type ". $dbh->{Driver}->{Name}.
+ "; guessing how to convert to UNIX timestamps";
+ $str2time = 'extract(epoch from ';
+ }
+
+ #find closed sessions completely within the given range
+ my $sth = $dbh->prepare("SELECT SUM(acctsessiontime)
+ FROM radacct
+ WHERE UserName = ?
+ AND $str2time AcctStartTime) >= ?
+ AND $str2time AcctStopTime ) < ?
+ AND AcctStopTime =! 0
+ AND AcctStopTime IS NOT NULL"
+ ) or die $dbh->errstr;
+ $sth->execute($username, $start, $end) or die $sth->errstr;
+ my $regular = $sth->fetchrow_arrayref->[0];
+
+ #find open sessions which start in the range, count session start->range end
+ # don't count them if they are over 1 day old (probably missing stop record)
+ $sth = $dbh->prepare("SELECT SUM( ? - $str2time AcctStartTime ) )
+ FROM radacct
+ WHERE UserName = ?
+ AND $str2time AcctStartTime ) >= ?
+ AND ( ? - $str2time AcctStartTime ) < 86400
+ AND ( AcctStopTime = 0
+ OR AcctStopTime IS NULL )"
+ ) or die $dbh->errstr;
+ $sth->execute($end, $username, $start, $end) or die $sth->errstr;
+ my $start_during = $sth->fetchrow_arrayref->[0];
+
+ #find closed sessions which start before the range but stop during,
+ #count range start->session end
+ $sth = $dbh->prepare("SELECT SUM( $str2time AcctStopTime ) - ? )
+ FROM radacct
+ WHERE UserName = ?
+ AND $str2time AcctStartTime ) < ?
+ AND $str2time AcctStopTime ) >= ?
+ AND $str2time AcctStopTime ) < ?
+ AND AcctStopTime != 0
+ AND AcctStopTime IS NOT NULL"
+ ) or die $dbh->errstr;
+ $sth->execute($start, $username, $start, $start, $end ) or die $sth->errstr;
+ my $end_during = $sth->fetchrow_arrayref->[0];
+
+ #find closed (not anymore - or open) sessions which start before the range
+ # but stop # after, or are still open, count range start->range end
+ # don't count open sessions (probably missing stop record)
+ $sth = $dbh->prepare("SELECT COUNT(*)
+ FROM radacct
+ WHERE UserName = ?
+ AND $str2time AcctStartTime ) < ?
+ AND ( $str2time AcctStopTime ) >= ?
+ )"
+ # OR AcctStopTime = 0
+ # OR AcctStopTime IS NULL )"
+ ) or die $dbh->errstr;
+ $sth->execute($username, $start, $end ) or die $sth->errstr;
+ my $entire_range = ($end-$start) * $sth->fetchrow_arrayref->[0];
+
+ $seconds += $regular + $end_during + $start_during + $entire_range;
+
}
- #find sessions completely within the given range
- my $sth = $dbh->prepare("SELECT SUM(acctsessiontime)
- FROM radacct
- WHERE UserName = ?
- AND $str2time AcctStartTime) >= ?
- AND $str2time AcctStopTime ) < ?
- AND AcctStopTime =! 0
- AND AcctStopTime IS NOT NULL"
- ) or die $dbh->errstr;
- $sth->execute($username, $start, $end) or die $sth->errstr;
- my $regular = $sth->fetchrow_arrayref->[0];
-
- #find open sessions which start in the range, count session start->range end
- $sth = $dbh->prepare("SELECT SUM( ? - $str2time AcctStartTime ) )
- FROM radacct
- WHERE UserName = ?
- AND AcctStartTime >= ?
- AND ( AcctStopTime = 0
- OR AcctStopTime IS NULL )"
- ) or die $dbh->errstr;
- $sth->execute($end, $username, $start) or die $sth->errstr;
- my $start_during = $sth->fetchrow_arrayref->[0];
-
- #find closed sessions which start before the range but stop during,
- #count range start->session end
- $sth = $dbh->prepare("SELECT SUM( $str2time AcctStopTime ) - ? )
- FROM radacct
- WHERE UserName = ?
- AND AcctStartTime < ?
- AND AcctStopTime >= ?
- AND AcctStopTime < ?
- AND AcctStopTime != 0
- AND AcctStopTime IS NOT NULL"
- ) or die $dbh->errstr;
- $sth->execute($start, $username, $start, $start, $end ) or die $sth->errstr;
- my $end_during = $sth->fetchrow_arrayref->[0];
-
- #find closed or open sessions which start before the range but stop
- # after, or are still open, count range start->range end
- $sth = $dbh->prepare("SELECT COUNT(*)
- FROM radacct
- WHERE UserName = ?
- AND AcctStartTime < ?
- AND ( AcctStopTime >= ?
- OR AcctStopTime = 0
- OR AcctStopTime IS NULL )"
- ) or die $dbh->errstr;
- $sth->execute($username, $start, $end ) or die $sth->errstr;
- my $entire_range = ($end-$start) * $sth->fetchrow_arrayref->[0];
+ $seconds;
- $regular + $end_during + $start_during + $entire_range;
}
=back
=head1 VERSION
-$Id: cust_svc.pm,v 1.18 2002-10-12 13:26:45 ivan Exp $
+$Id: cust_svc.pm,v 1.19 2002-10-17 14:16:17 ivan Exp $
=head1 BUGS
$self->cust_svc->seconds_since(@_);
}
-=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END DATASRC DB_USERNAME DB_PASSWORD
+=item seconds_since_sqlradacct TIMESTAMP_START TIMESTAMP_END
Returns the numbers of seconds this account has been online between
TIMESTAMP_START (inclusive) and TIMESTAMP_END (exclusive), according to an
-external SQL radacct table, such as those generated by ICRADIUS or FreeRADIUS.
-Sessions which started in the specified range but are still open are counted
-from session start to the end of the range. Also, sessions which end in the
-range but started earlier are counted from the start of the range to session
-end. Finally, sessions which start before the range but end after (or are
-still open) are counted for the entire range.
+external SQL radacct table, specified via sqlradius export. Sessions which
+started in the specified range but are still open are counted from session
+start to the end of the range (unless they are over 1 day old, in which case
+they are presumed missing their stop record and not counted). Also, sessions
+which end in therange but started earlier are counted from the start of the
+range to session end. Finally, sessions which start before the range but end
+after are counted for the entire range.
TIMESTAMP_START and TIMESTAMP_END are specified as UNIX timestamps; see
L<perlfunc/"time">. Also see L<Time::Local> and L<Date::Parse> for conversion
},
'sqlradacct_hour' => {
- 'name' => 'Base charge plus charge per-hour from an external SQL radacct table',
+ 'name' => 'Base charge plus charge per-hour from an external sqlradius radacct table',
'fields' => {
'setup_fee' => { 'name' => 'Setup fee for this package',
'default' => 0,
'recur_flat' => { 'name' => 'Base monthly charge for this package',
'default' => 0,
},
- 'sql_datasrc' => { 'name' => 'DBI data source',
- 'default' => 'DBI:mysql:host=radius.server.name;dbname=radius',
- },
- 'sql_username' => { 'name' => 'Database username',
- 'default' => 'radius',
- },
- 'sql_password' => { 'name' => 'Database password',
- 'default' => '',
- },
'recur_included_hours' => { 'name' => 'Hours included',
'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_sqlradacct($cust_pkg->last_bill, $sdate, \' + what.sql_datasrc + \', \' + what.sql_username + \', \' + what.sql_password + \' ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'',
+ 'recur' => '\'my $hours = $cust_pkg->seconds_since_sqlradacct($cust_pkg->last_bill, $sdate ) / 3600 - \' + what.recur_included_hours.value + \'; $hours = 0 if $hours < 0; \' + what.recur_flat.value + \' + \' + what.recur_hourly_charge.value + \' * $hours;\'',
},