1 % if ( @include_agents ) {
3 <& /elements/header.html, $title &>
4 % foreach my $agent ( @include_agents ) {
5 % $cgi->param('agentnum', $agent->agentnum); #for download links
6 <DIV WIDTH="100%" STYLE="page-break-after: always">
7 <FONT SIZE=6><% $agent->agent %></FONT><BR><BR>
8 <& sqlradius_usage.html,
10 agentnum => $agent->agentnum,
12 usage_by_username => \%usage_by_username,
13 download_label => 'Download this section',
18 <& /elements/footer.html &>
20 <& elements/search.html,
23 'query' => $sql_query,
24 'count_query' => $sql_query->{'count_query'},
25 'header' => [ #FS::UI::Web::cust_header(),
35 'fields' => [ #\&FS::UI::Web::cust_fields,
42 'links' => [ #( map { $_ ne 'Cust. Status' ? $link_cust : '' }
43 # FS::UI::Web::cust_header() ),
47 ( map { $link_svc } @svc_header ),
52 'align' => #FS::UI::Web::cust_aligns() .
53 'rlc' . ('l' x scalar(@svc_header)) . 'rrr' ,
54 'nohtmlheader' => ($opt{'nohtmlheader'} || 0),
55 'download_label' => $opt{'download_label'},
62 die "access denied" unless
63 $FS::CurrentUser::CurrentUser->access_right('List services');
65 my $title = 'Data Usage Report - ';
69 if ( $opt{'agentnum'} ) {
70 $agentnum = $opt{'agentnum'};
71 } elsif ( $cgi->param('agentnum') =~ /^(\d+)$/ ) {
76 my $agent = FS::agent->by_key($agentnum);
77 $title = $agent->agent." $title";
79 @include_agents = qsearch('agent', {});
83 my( $beginning, $ending ) = FS::UI::Web::parse_beginning_ending($cgi);
86 $title .= time2str('%h %o %Y ', $beginning);
89 if ( $ending == 4294967295 ) {
92 $title .= time2str('%h %o %Y', $ending);
96 my %usage_by_username;
97 if ( exists($opt{usage_by_username}) ) {
98 # There's no agent separation in the radacct data. So in the jumbo report
99 # do this procedure once, and pass the hash into all the per-agent sections.
100 %usage_by_username = %{ $opt{usage_by_username} };
101 $export = $opt{export};
104 $cgi->param('exportnum') =~ /^(\d+)$/
105 or die "illegal export: '".$cgi->param('exportnum')."'";
106 $export = FS::part_export->by_key($1)
107 or die "exportnum $1 not found";
108 $export->exporttype =~ /sqlradius/
109 or die "exportnum ".$export->exportnum." is type ".$export->exporttype.
112 my $usage = $export->usage_sessions( {
113 stoptime_start => $beginning,
114 stoptime_end => $ending,
117 # arrayref of hashrefs of
118 # (username, acctsessiontime, acctinputoctets, acctoutputoctets)
119 # (XXX needs to include 'realm' for sqlradius_withdomain)
120 # rearrange to be indexed by username.
123 my $username = $_->{'username'};
125 $_->{'acctinputoctets'},
126 $_->{'acctoutputoctets'},
127 $_->{'acctinputoctets'} + $_->{'acctoutputoctets'}
129 $usage_by_username{$username} = \@row;
133 #warn Dumper(\%usage_by_username);
134 my @total_usage = (0, 0, 0, 0); # session time, input, output, input + output
135 my @svc_usage = map {
138 my $username = $export->export_username(shift);
139 return '' if !exists($usage_by_username{$username});
140 my $value = $usage_by_username{ $username }->[$i];
141 $total_usage[$i] += $value;
142 # for now, always show in GB, rounded to 3 digits
147 # set up svcdb-specific stuff
148 my $export_username = sub {
149 $export->export_username(shift); # countrycode + phone, formatted MAC, etc.
153 svc_acct => [ 'Username' ],
154 svc_broadband => [ 'MAC address', 'IP address' ],
155 # svc_phone => [ 'Phone' ], #not yet supported, no search method
156 # (not sure input/output octets is relevant)
159 svc_acct => [ $export_username ],
160 svc_broadband => [ $export_username, 'ip_addr' ],
161 # svc_phone => [ $export_username ],
164 # what kind of service we're operating on
165 my $svcdb = FS::part_export::export_info()->{$export->exporttype}->{'svc'};
166 my $class = "FS::$svcdb";
167 my @svc_header = @{ $svc_header{$svcdb} };
168 my @svc_fields = @{ $svc_fields{$svcdb} };
170 # svc_x search params
171 my %search_hash = ( 'agentnum' => $agentnum,
172 'exportnum' => $export->exportnum );
174 my $sql_query = $class->search(\%search_hash);
175 $sql_query->{'select'} .= ', part_pkg.pkg';
176 $sql_query->{'addl_from'} .= ' LEFT JOIN part_pkg USING (pkgpart)';
178 my $link_svc = [ $p.'view/cust_svc.cgi?', 'svcnum' ];
180 my $link_cust = [ $p.'view/cust_main.cgi?', 'custnum' ];
182 # columns between the customer name and the usage fields
183 my $skip_cols = 1 + scalar(@svc_header);
187 FS::Record->scalar_sql($sql_query->{count_query}) . ' services',
191 sub { # defer this until the rows have been processed
192 bytes_to_gb($total_usage[$i])
198 $_[0] ? sprintf('%.3f', $_[0] / (1024*1024*1024.0)) : '';