package FS::cust_svc;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $ignore_quantity );
use Carp qw( cluck );
use FS::Record qw( qsearch qsearchs dbh );
use FS::cust_pkg;
use FS::svc_acct;
use FS::svc_domain;
use FS::svc_forward;
+use FS::svc_broadband;
use FS::domain_record;
use FS::part_export;
@ISA = qw( FS::Record );
+$ignore_quantity = 0;
+
sub _cache {
my $self = shift;
my ( $hashref, $cache ) = @_;
});
return "Already ". scalar(@cust_svc). " ". $part_svc->svc.
" services for pkgnum ". $self->pkgnum
- if scalar(@cust_svc) >= $quantity;
+ if scalar(@cust_svc) >= $quantity && !$ignore_quantity;
}
- ''; #no error
+ $self->SUPER::check;
}
=item part_svc
if ( $svcdb eq 'svc_acct' ) {
$tag = $svc_x->email;
} elsif ( $svcdb eq 'svc_forward' ) {
- my $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $svc_x->srcsvc } );
- $tag = $svc_acct->email. '->';
+ if ( $svc_x->srcsvc ) {
+ my $svc_acct = $svc_x->srcsvc_acct;
+ $tag = $svc_acct->email;
+ } else {
+ $tag = $svc_x->src;
+ }
+ $tag .= '->';
if ( $svc_x->dstsvc ) {
- $svc_acct = qsearchs( 'svc_acct', { 'svcnum' => $svc_x->dstsvc } );
+ my $svc_acct = $svc_x->dstsvc_acct;
$tag .= $svc_acct->email;
} else {
$tag .= $svc_x->dst;
$tag = $domain->zone;
} elsif ( $svcdb eq 'svc_broadband' ) {
$tag = $svc_x->ip_addr;
+ } elsif ( $svcdb eq 'svc_external' ) {
+ $tag = $svc_x->id. ': '. $svc_x->title;
} else {
cluck "warning: asked for label of unsupported svcdb; using svcnum";
$tag = $svc_x->getfield('svcnum');
sub seconds_since_sqlradacct {
my($self, $start, $end) = @_;
- my $username = $self->svc_x->username;
+ my $svc_x = $self->svc_x;
- my @part_export = $self->part_svc->part_export('sqlradius')
- or die "no sqlradius export configured for this service type";
+ my @part_export = $self->part_svc->part_export('sqlradius');
+ push @part_export, $self->part_svc->part_export('sqlradius_withdomain');
+ die "no sqlradius or sqlradius_withdomain export configured for this".
+ "service type"
+ unless @part_export;
#or return undef;
my $seconds = 0;
foreach my $part_export ( @part_export ) {
+ next if $part_export->option('ignore_accounting');
+
my $dbh = DBI->connect( map { $part_export->option($_) }
qw(datasrc username password) )
or die "can't connect to sqlradius database: ". $DBI::errstr;
$str2time = 'extract(epoch from ';
}
+ my $username;
+ if ( $part_export->exporttype eq 'sqlradius' ) {
+ $username = $svc_x->username;
+ } elsif ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
+ $username = $svc_x->email;
+ } else {
+ die 'unknown exporttype '. $part_export->exporttype;
+ }
+
my $query;
#find closed sessions completely within the given range
sub attribute_since_sqlradacct {
my($self, $start, $end, $attrib) = @_;
- my $username = $self->svc_x->username;
+ my $svc_x = $self->svc_x;
- my @part_export = $self->part_svc->part_export('sqlradius')
- or die "no sqlradius export configured for this service type";
+ my @part_export = $self->part_svc->part_export('sqlradius');
+ push @part_export, $self->part_svc->part_export('sqlradius_withdomain');
+ die "no sqlradius or sqlradius_withdomain export configured for this".
+ "service type"
+ unless @part_export;
#or return undef;
my $sum = 0;
foreach my $part_export ( @part_export ) {
+ next if $part_export->option('ignore_accounting');
+
my $dbh = DBI->connect( map { $part_export->option($_) }
qw(datasrc username password) )
or die "can't connect to sqlradius database: ". $DBI::errstr;
$str2time = 'extract(epoch from ';
}
+ my $username;
+ if ( $part_export->exporttype eq 'sqlradius' ) {
+ $username = $svc_x->username;
+ } elsif ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
+ $username = $svc_x->email;
+ } else {
+ die 'unknown exporttype '. $part_export->exporttype;
+ }
+
my $sth = $dbh->prepare("SELECT SUM($attrib)
FROM radacct
WHERE UserName = ?
}
+=item get_session_history_sqlradacct TIMESTAMP_START TIMESTAMP_END
+
+See L<FS::svc_acct/get_session_history_sqlradacct>. Equivalent to
+$cust_svc->svc_x->get_session_history_sqlradacct, but more efficient.
+Meaningless for records where B<svcdb> is not "svc_acct".
+
+=cut
+
+sub get_session_history {
+ my($self, $start, $end, $attrib) = @_;
+
+ my $username = $self->svc_x->username;
+
+ my @part_export = $self->part_svc->part_export('sqlradius')
+ or die "no sqlradius export configured for this service type";
+ #or return undef;
+
+ my @sessions = ();
+
+ foreach my $part_export ( @part_export ) {
+
+ my $dbh = DBI->connect( map { $part_export->option($_) }
+ qw(datasrc username password) )
+ or die "can't connect to sqlradius database: ". $DBI::errstr;
+
+ #select a unix time conversion function based on database type
+ my $str2time;
+ if ( $dbh->{Driver}->{Name} eq 'mysql' ) {
+ $str2time = 'UNIX_TIMESTAMP(';
+ } elsif ( $dbh->{Driver}->{Name} eq 'Pg' ) {
+ $str2time = 'EXTRACT( EPOCH FROM ';
+ } else {
+ warn "warning: unknown database type ". $dbh->{Driver}->{Name}.
+ "; guessing how to convert to UNIX timestamps";
+ $str2time = 'extract(epoch from ';
+ }
+
+ my @fields = qw( acctstarttime acctstoptime acctsessiontime
+ acctinputoctets acctoutputoctets framedipaddress );
+
+ my $sth = $dbh->prepare('SELECT '. join(', ', @fields).
+ " FROM radacct
+ WHERE UserName = ?
+ AND $str2time AcctStopTime ) >= ?
+ AND $str2time AcctStopTime ) <= ?
+ ORDER BY AcctStartTime DESC
+ ") or die $dbh->errstr;
+ $sth->execute($username, $start, $end) or die $sth->errstr;
+
+ push @sessions, map { { %$_ } } @{ $sth->fetchall_arrayref({}) };
+
+ }
+ \@sessions
+
+}
+
=back
=head1 BUGS