1 <% include( '/elements/header.html', 'RADIUS Sessions') %>
4 % # and finally, display the thing
7 % foreach my $part_export ( @part_export ) {
11 % my $efields = tie my %efields, 'Tie::IxHash', %fields;
12 % delete $efields{'framedipaddress'} if $part_export->option('hide_ip');
13 % if ( $part_export->option('hide_data') ) {
14 % delete $efields{$_} foreach qw(acctinputoctets acctoutputoctets);
17 <FONT CLASS="fsinnerbox-title">
18 <% $part_export->exportname || $part_export->exporttype |h %>
19 <% $part_export->machine ? ' to '. $part_export->machine : '' |h %>
22 <% include( '/elements/table-grid.html' ) %>
23 % my $bgcolor1 = '#eeeeee';
24 % my $bgcolor2 = '#ffffff';
28 % foreach my $field ( keys %efields ) {
30 <TH CLASS="grid" BGCOLOR="#cccccc">
31 <% $efields{$field}->{name} %><BR>
32 <FONT SIZE=-2><% $efields{$field}->{attrib} %></FONT>
38 % foreach my $session (
39 % @{ $part_export->usage_sessions( {
40 % 'stoptime_start' => $beginning,
41 % 'stoptime_end' => $ending,
42 % 'session_status' => $status,
43 % 'starttime_start' => $starttime_beginning,
44 % 'starttime_end' => $starttime_ending,
47 % 'prefix' => $prefix,
48 % 'summarize' => $summarize,
52 % if ( $bgcolor eq $bgcolor1 ) {
53 % $bgcolor = $bgcolor2;
55 % $bgcolor = $bgcolor1;
59 % foreach my $field ( keys %efields ) {
60 % my $html = &{ $efields{$field}->{fmt} }( $session->{$field},
64 % my $class = ( $html =~ /<TABLE/ ? 'inv' : 'grid' );
66 <TD CLASS="<%$class%>" BGCOLOR="<% $bgcolor %>" ALIGN="<% $efields{$field}->{align} %>">
82 unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
89 $summarize = 1 if $cgi->param('summarize') eq 'Y';
91 #sort of false laziness w/cust_pay.cgi
92 my( $beginning, $ending ) = ( '', '' );
93 if ( $cgi->param('stoptime_beginning')
94 && $cgi->param('stoptime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
95 $beginning = parse_datetime($1);
97 if ( $cgi->param('stoptime_ending')
98 && $cgi->param('stoptime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
99 $ending = parse_datetime($1); # + 86399;
101 if ( $cgi->param('begin') && $cgi->param('begin') =~ /^(\d+)$/ ) {
104 if ( $cgi->param('end') && $cgi->param('end') =~ /^(\d+)$/ ) {
109 if ( $cgi->param('session_status') =~ /^(closed|open)$/ ) {
113 my( $starttime_beginning, $starttime_ending ) = ( '', '' );
114 if ( $cgi->param('starttime_beginning')
115 && $cgi->param('starttime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
116 $starttime_beginning = parse_datetime($1);
118 if ( $cgi->param('starttime_ending')
119 && $cgi->param('starttime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
120 $starttime_ending = parse_datetime($1); # + 86399;
124 if ( $cgi->param('svcnum') =~ /^(\d+)$/ ) {
125 $cgi_svc = qsearchs( 'svc_acct', { 'svcnum' => $1 } )
126 || qsearchs( 'svc_broadband', { 'svcnum' => $1 } );
127 } elsif ( $cgi->param('username') =~ /^([^@]+)\@([^@]+)$/ ) {
128 my %search = { 'username' => $1 };
129 my $svc_domain = qsearchs('svc_domain', { 'domain' => $2 } );
131 $search{'domsvc'} = $svc_domain->svcnum;
133 delete $search{'username'};
135 $cgi_svc = qsearchs( 'svc_acct', \%search )
137 } elsif ( $cgi->param('username') =~ /^(.+)$/ ) {
138 $cgi_svc = qsearchs( 'svc_acct', { 'username' => $1 } );
141 my @part_export = ();
143 my $part_svc = $cgi_svc->cust_svc->part_svc;
145 $part_svc->part_export('sqlradius'),
146 $part_svc->part_export('sqlradius_withdomain'),
147 $part_svc->part_export('broadband_sqlradius'),
151 #grep $_->can('usage_sessions'), qsearch( 'part_export' )
152 qsearch( 'part_export', { 'exporttype' => 'sqlradius' } ),
153 qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } ),
154 qsearch( 'part_export', { 'exporttype' => 'broadband_sqlradius' } ),
159 if ( $cgi->param('ip') =~ /^((\d+\.){3}\d+)$/ ) {
163 my $prefix = $cgi->param('prefix');
165 if ( $prefix =~ /^(\d+)$/ ) {
167 $prefix = "011$prefix" unless $prefix =~ /^1/;
173 # field formatting subroutines
177 my $user_format = sub {
178 my ( $user, $session, $part_export ) = @_;
181 if ( exists $user2svc{$user} ) {
182 $svc = $user2svc{$user};
185 if ( $part_export->exporttype eq 'broadband_sqlradius' ) {
187 ( my $mac = $user ) =~ s/[^0-9a-f]//ig;
190 grep { qsearchs( 'export_svc', {
191 'exportnum' => $part_export->exportnum,
192 'svcpart' => $_->cust_svc->svcpart,
194 } qsearch( 'svc_broadband', {
195 mac_addr => { op=>'ILIKE', value=>$mac }
198 if ( @svc_broadband ) {
199 warn 'multiple svc_broadband records for user $user found; '.
200 'using first arbitrarily'
201 if scalar(@svc_broadband) > 1;
202 $user2svc{$user} = $svc = shift @svc_broadband;
208 if ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
210 if ( $user =~ /^([^@]+)\@([^@]+)$/ ) {
211 $search{'username'} = $1;
214 $search{'username'} = $user;
215 $domain = $session->{'realm'};
217 my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } );
219 $search{'domsvc'} = $svc_domain->svcnum;
221 delete $search{'username'};
223 } elsif ( $part_export->exporttype eq 'sqlradius' ) {
224 $search{'username'} = $user;
226 die 'unknown export type '. $part_export->exporttype.
227 " for $part_export\n";
229 if ( keys %search ) {
231 grep { qsearchs( 'export_svc', {
232 'exportnum' => $part_export->exportnum,
233 'svcpart' => $_->cust_svc->svcpart,
235 } qsearch( 'svc_acct', \%search );
237 warn 'multiple svc_acct records for user $user found; '.
238 'using first arbitrarily'
239 if scalar(@svc_acct) > 1;
240 $user2svc{$user} = $svc = shift @svc_acct;
250 #i should use svc_link, but that's expensive per-user
251 my $svcnum = $svc->svcnum;
252 my $table = $svc->table;
253 qq(<A HREF="${p}view/$table.cgi?$svcnum"><B>$user</B></A>);
261 my $customer_format = sub {
262 my( $unused, $session ) = @_;
263 return ' ' unless exists $user2svc{$session->{'username'}};
264 my $svc = $user2svc{$session->{'username'}};
265 my $cust_pkg = $svc->cust_svc->cust_pkg;
266 return ' ' unless $cust_pkg;
267 my $cust_main = $cust_pkg->cust_main;
269 qq!<A HREF="${p}view/cust_main.cgi?!. $cust_main->custnum. '">'.
270 $cust_pkg->cust_main->name. '</A>';
273 my $time_format = sub {
275 return ' ' if $time == 0;
276 my $pretty = time2str('%T%P %a %b %o %Y', $time );
277 $pretty =~ s/ (\d)(st|dn|rd|th)/$1$2/;
281 my $time_format_or_open = sub {
283 return '<CENTER>OPEN</CENTER>' if $time == 0;
284 &{$time_format}($time);
287 my $duration_format = sub {
289 return '' if $seconds eq ''; # open session
290 my $hour = int($seconds/3600);
291 my $min = int( ($seconds%3600) / 60 );
292 my $sec = $seconds%60;
293 '<TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0>'.
294 '<TR><TD CLASS="inv" ALIGN="right">'.
295 ( $hour ? "<B>$hour</B>h" : ' ' ).
296 '</TD><TD CLASS="inv" ALIGN="right">'.
297 ( ( $hour || $min ) ? "<B>$min</B>m" : ' ' ).
298 '</TD><TD CLASS="inv" ALIGN="right">'.
300 '</TD></TR></TABLE>';
303 my $octets_format = sub {
305 my $megs = $octets / 1048576;
306 sprintf('<B>%.3f</B> megs', $megs);
307 #my $gigs = $octets / 1073741824
308 #sprintf('<B>%.3f</B> gigabytes', $gigs);
317 tie %fields, 'Tie::IxHash',
320 attrib => 'UserName',
327 fmt => $customer_format,
330 'acctsessiontime' => {
332 attrib => 'Acct-Session-Time',
333 fmt => $duration_format,
336 'acctinputoctets' => {
337 name => 'Upload', # (from user)',
338 attrib => 'Acct-Input-Octets',
339 fmt => $octets_format,
342 'acctoutputoctets' => {
343 name => 'Download', # (to user)',
344 attrib => 'Acct-Output-Octets',
345 fmt => $octets_format,
350 tie %fields, 'Tie::IxHash',
353 attrib => 'UserName',
365 fmt => $customer_format,
368 'framedipaddress' => {
369 name => 'IP Address',
370 attrib => 'Framed-IP-Address',
371 fmt => sub { my $ip = shift;
372 length($ip) ? $ip : ' ';
376 'callingstationid' => {
377 name => 'Source or MAC',
378 attrib => 'Calling-Station-Id',
382 /^\s*(([\dA-F]{2}[\-:]){5}[\dA-F]{2})/i ) {
384 (Net::MAC::Vendor::lookup($1))->[0].
388 length($src) ? $src : ' ';
392 'calledstationid' => {
393 name => 'Destination',
394 attrib => 'Called-Station-ID',
398 /^\s*(([\dA-F]{2}[\-:]){5}[\dA-F]{2})/i ) {
400 (Net::MAC::Vendor::lookup($1))->[0].
403 length($dst) ? $dst : ' ';
408 name => 'Start time',
409 attrib => 'Acct-Start-Time',
414 name => 'End time',
415 attrib => 'Acct-Stop-Time',
416 fmt => $time_format_or_open,
419 'acctsessiontime' => {
421 attrib => 'Acct-Session-Time',
422 fmt => $duration_format,
425 'acctinputoctets' => {
426 name => 'Upload', # (from user)',
427 attrib => 'Acct-Input-Octets',
428 fmt => $octets_format,
431 'acctoutputoctets' => {
432 name => 'Download', # (to user)',
433 attrib => 'Acct-Output-Octets',
434 fmt => $octets_format,
439 $fields{$_}->{fmt} ||= sub { length($_[0]) ? shift : ' '; }
440 foreach keys %fields;