fix RADIUS session report for svc_broadband sessions, RT#26461
[freeside.git] / httemplate / search / sqlradius.cgi
1 <% include( '/elements/header.html', 'RADIUS Sessions') %>
2
3 % ###
4 % # and finally, display the thing
5 % ### 
6 %
7 % foreach my $part_export ( @part_export ) {
8 %
9 %   %user2svc = ();
10 %
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);
15 %   }
16 %   if ( $part_export->option('show_called_station') ) {
17 %     $efields->Splice(1, 0,
18 %       'calledstationid' => {
19 %                              'name'   => 'Destination',
20 %                              'attrib' => 'Called-Station-ID',
21 %                              'fmt'    =>
22 %                                sub { length($_[0]) ? shift : '&nbsp'; },
23 %                              'align'  => 'left',
24 %                            },
25 %     );
26 %   }
27
28     <FONT CLASS="fsinnerbox-title">
29       <% $part_export->exportname || $part_export->exporttype |h %>
30       <% $part_export->machine ? ' to '. $part_export->machine : '' |h %>
31     </FONT><BR>
32
33     <% include( '/elements/table-grid.html' ) %>
34 %   my $bgcolor1 = '#eeeeee';
35 %   my $bgcolor2 = '#ffffff';
36 %   my $bgcolor;
37
38     <TR>
39 %   foreach my $field ( keys %efields ) { 
40
41       <TH CLASS="grid" BGCOLOR="#cccccc">
42         <% $efields{$field}->{name} %><BR>
43         <FONT SIZE=-2><% $efields{$field}->{attrib} %></FONT>
44       </TH>
45
46 %   } 
47   </TR>
48
49 %   foreach my $session (
50 %       @{ $part_export->usage_sessions( {
51 %            'stoptime_start'  => $beginning,
52 %            'stoptime_end'    => $ending,
53 %            'session_status'  => $status,
54 %            'starttime_start' => $starttime_beginning,
55 %            'starttime_end'   => $starttime_ending,
56 %            'svc'             => $cgi_svc,
57 %            'ip'              => $ip,
58 %            'prefix'          => $prefix, 
59 %            'summarize'       => $summarize,
60 %          } )
61 %       }
62 %   ) {
63 %     if ( $bgcolor eq $bgcolor1 ) {
64 %       $bgcolor = $bgcolor2;
65 %     } else {
66 %       $bgcolor = $bgcolor1;
67 %     }
68
69       <TR>
70 %     foreach my $field ( keys %efields ) { 
71 %       my $html = &{ $efields{$field}->{fmt} }( $session->{$field},
72 %                                                $session,
73 %                                                $part_export,
74 %                                              );
75 %       my $class = ( $html =~ /<TABLE/ ? 'inv' : 'grid' );
76
77         <TD CLASS="<%$class%>" BGCOLOR="<% $bgcolor %>" ALIGN="<% $efields{$field}->{align} %>">
78           <% $html %>
79         </TD>
80 %     } 
81   </TR>
82
83 %   } 
84
85 </TABLE>
86 <BR><BR>
87
88 % } 
89
90 <%init>
91
92 die "access denied"
93   unless $FS::CurrentUser::CurrentUser->access_right('List rating data');
94
95 ###
96 # parse cgi params
97 ###
98
99 my $summarize = 0;
100 $summarize = 1 if $cgi->param('summarize') eq 'Y';
101
102 #sort of false laziness w/cust_pay.cgi
103 my( $beginning, $ending ) = ( '', '' );
104 if ( $cgi->param('stoptime_beginning')
105      && $cgi->param('stoptime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
106   $beginning = parse_datetime($1);
107 }
108 if ( $cgi->param('stoptime_ending')
109      && $cgi->param('stoptime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
110   $ending = parse_datetime($1); # + 86399;
111 }
112 if ( $cgi->param('begin') && $cgi->param('begin') =~ /^(\d+)$/ ) {
113   $beginning = $1;
114 }
115 if ( $cgi->param('end') && $cgi->param('end') =~ /^(\d+)$/ ) {
116   $ending = $1;
117 }
118
119 my $status = '';
120 if ( $cgi->param('session_status') =~ /^(closed|open)$/ ) {
121   $status = $1;
122 }
123
124 my( $starttime_beginning, $starttime_ending ) = ( '', '' );
125 if ( $cgi->param('starttime_beginning')
126      && $cgi->param('starttime_beginning') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
127   $starttime_beginning = parse_datetime($1);
128 }
129 if ( $cgi->param('starttime_ending')
130      && $cgi->param('starttime_ending') =~ /^([ 0-9\-\/\:\w]{0,54})$/ ) {
131   $starttime_ending = parse_datetime($1); # + 86399;
132 }
133
134 my $cgi_svc = '';
135 if ( $cgi->param('svcnum') =~ /^(\d+)$/ ) {
136   $cgi_svc =  qsearchs( 'svc_acct',      { 'svcnum' => $1 } )
137            || qsearchs( 'svc_broadband', { 'svcnum' => $1 } );
138 } elsif ( $cgi->param('username') =~ /^([^@]+)\@([^@]+)$/ ) {
139   my %search = { 'username' => $1 };
140   my $svc_domain = qsearchs('svc_domain', { 'domain' => $2 } );
141   if ( $svc_domain ) {
142     $search{'domsvc'} = $svc_domain->svcnum;
143   } else {
144     delete $search{'username'};
145   }
146   $cgi_svc = qsearchs( 'svc_acct', \%search )
147     if keys %search;
148 } elsif ( $cgi->param('username') =~ /^(.+)$/ ) {
149   $cgi_svc = qsearchs( 'svc_acct', { 'username' => $1 } );
150 }
151
152 my @part_export = ();
153 if ( $cgi_svc ) {
154   my $part_svc = $cgi_svc->cust_svc->part_svc;
155   @part_export = (
156     $part_svc->part_export('sqlradius'),
157     $part_svc->part_export('sqlradius_withdomain'),
158     $part_svc->part_export('broadband_sqlradius'),
159   );
160 } else {
161   @part_export = (
162     #grep $_->can('usage_sessions'), qsearch( 'part_export' )
163     qsearch( 'part_export', { 'exporttype' => 'sqlradius' } ),
164     qsearch( 'part_export', { 'exporttype' => 'sqlradius_withdomain' } ),
165     qsearch( 'part_export', { 'exporttype' => 'broadband_sqlradius' } ),
166   );
167 }
168
169 my $ip = '';
170 if ( $cgi->param('ip') =~ /^((\d+\.){3}\d+)$/ ) {
171   $ip = $1;
172 }
173
174 my $prefix = $cgi->param('prefix');
175 $prefix =~ s/\D//g;
176 if ( $prefix =~ /^(\d+)$/ ) {
177   $prefix = $1;
178   $prefix = "011$prefix" unless $prefix =~ /^1/;
179 } else {
180   $prefix = '';
181 }
182
183 ###
184 # field formatting subroutines
185 ###
186
187 my %user2svc = ();
188 my $user_format = sub {
189   my ( $user, $session, $part_export ) = @_;
190
191   my $svc = '';
192   if ( exists $user2svc{$user} ) {
193     $svc = $user2svc{$user};
194   } else {
195
196     if ( $part_export->exporttype eq 'broadband_sqlradius' ) {
197
198       ( my $mac = $user ) =~ s/[^0-9a-f]//ig;
199
200       my @svc_broadband =
201         grep { qsearchs( 'export_svc', {
202                  'exportnum' => $part_export->exportnum,
203                  'svcpart'   => $_->cust_svc->svcpart,
204                } )
205              } qsearch( 'svc_broadband', {
206                           mac_addr => { op=>'ILIKE', value=>$mac }
207                       });
208
209       if ( @svc_broadband ) {
210         warn 'multiple svc_broadband records for user $user found; '.
211              'using first arbitrarily'
212           if scalar(@svc_broadband) > 1;
213         $user2svc{$user} = $svc = shift @svc_broadband;
214       }
215
216     } else {
217
218       my %search = ();
219       if ( $part_export->exporttype eq 'sqlradius_withdomain' ) {
220         my $domain;
221         if ( $user =~ /^([^@]+)\@([^@]+)$/ ) {
222          $search{'username'} = $1;
223          $domain = $2;
224        } else {
225          $search{'username'} = $user;
226          $domain = $session->{'realm'};
227        }
228        my $svc_domain = qsearchs('svc_domain', { 'domain' => $domain } );
229        if ( $svc_domain ) {
230          $search{'domsvc'} = $svc_domain->svcnum;
231        } else {
232          delete $search{'username'};
233        }
234       } elsif ( $part_export->exporttype eq 'sqlradius' ) {
235         $search{'username'} = $user;
236       } else {
237         die 'unknown export type '. $part_export->exporttype.
238             " for $part_export\n";
239       }
240       if ( keys %search ) {
241         my @svc_acct =
242           grep { qsearchs( 'export_svc', {
243                    'exportnum' => $part_export->exportnum,
244                    'svcpart'   => $_->cust_svc->svcpart,
245                  } )
246                } qsearch( 'svc_acct', \%search );
247         if ( @svc_acct ) {
248           warn 'multiple svc_acct records for user $user found; '.
249                'using first arbitrarily'
250             if scalar(@svc_acct) > 1;
251           $user2svc{$user} = $svc = shift @svc_acct;
252         }
253       } 
254
255     }
256
257   }
258
259   if ( $svc ) { 
260
261     #i should use svc_link, but that's expensive per-user
262     my $svcnum = $svc->svcnum;
263     my $table = $svc->table;
264     qq(<A HREF="${p}view/$table.cgi?$svcnum"><B>$user</B></A>);
265
266   } else {
267     "<B>$user</B>";
268   }
269
270 };
271
272 my $customer_format = sub {
273   my( $unused, $session ) = @_;
274   return '&nbsp;' unless exists $user2svc{$session->{'username'}};
275   my $svc = $user2svc{$session->{'username'}};
276   my $cust_pkg = $svc->cust_svc->cust_pkg;
277   return '&nbsp;' unless $cust_pkg;
278   my $cust_main = $cust_pkg->cust_main;
279
280   qq!<A HREF="${p}view/cust_main.cgi?!. $cust_main->custnum. '">'.
281     $cust_pkg->cust_main->name. '</A>';
282 };
283
284 my $time_format = sub {
285   my $time = shift;
286   return '&nbsp;' if $time == 0;
287   my $pretty = time2str('%T%P %a&nbsp;%b&nbsp;%o&nbsp;%Y', $time );
288   $pretty =~ s/ (\d)(st|dn|rd|th)/$1$2/;
289   $pretty;
290 };
291
292 my $time_format_or_open = sub {
293   my $time = shift;
294   return '<CENTER>OPEN</CENTER>' if $time == 0;
295   &{$time_format}($time);
296 };
297
298 my $duration_format = sub {
299   my $seconds = shift;
300   return '' if $seconds eq ''; # open session
301   my $hour = int($seconds/3600);
302   my $min = int( ($seconds%3600) / 60 );
303   my $sec = $seconds%60;
304   '<TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0>'.
305   '<TR><TD CLASS="inv" ALIGN="right">'.
306      ( $hour ? "<B>$hour</B>h" : '&nbsp;' ).
307    '</TD><TD CLASS="inv" ALIGN="right">'.
308      ( ( $hour || $min ) ? "<B>$min</B>m" : '&nbsp;' ).
309    '</TD><TD CLASS="inv" ALIGN="right">'.
310      "<B>$sec</B>s".
311   '</TD></TR></TABLE>';
312 };
313
314 my $octets_format = sub {
315   my $octets = shift;
316   my $megs = $octets / 1048576;
317   sprintf('<B>%.3f</B>&nbsp;megs', $megs);
318   #my $gigs = $octets / 1073741824
319   #sprintf('<B>%.3f</B> gigabytes', $gigs);
320 };
321
322 ###
323 # the fields
324 ###
325
326 my %fields;
327 if ( $summarize ) {
328 tie %fields, 'Tie::IxHash', 
329   'username'          => {
330                            name    => 'User',
331                            attrib  => 'UserName',
332                            fmt     => $user_format,
333                            align   => 'left',
334                          },
335   'dummy'             => {
336                            name    => 'Customer',
337                            attrib  => '',
338                            fmt     => $customer_format,
339                            align   => 'left',
340                          },
341   'acctsessiontime'   => {
342                            name    => 'Duration',
343                            attrib  => 'Acct-Session-Time',
344                            fmt     => $duration_format,
345                            align   => 'right',
346                          },
347   'acctinputoctets'   => {
348                            name    => 'Upload', # (from user)',
349                            attrib  => 'Acct-Input-Octets',
350                            fmt     => $octets_format,
351                            align   => 'right',
352                          },
353   'acctoutputoctets'  => {
354                            name    => 'Download', # (to user)',
355                            attrib  => 'Acct-Output-Octets',
356                            fmt     => $octets_format,
357                            align   => 'right',
358                          },
359 ;
360 } else {
361 tie %fields, 'Tie::IxHash',
362   'username'          => {
363                            name    => 'User',
364                            attrib  => 'UserName',
365                            fmt     => $user_format,
366                            align   => 'left',
367                          },
368   'realm'             => {
369                            name    => 'Realm',
370                            attrib  => 'Realm',
371                            align   => 'left',
372                          },
373   'dummy'             => {
374                            name    => 'Customer',
375                            attrib  => '',
376                            fmt     => $customer_format,
377                            align   => 'left',
378                          },
379   'framedipaddress'   => {
380                            name    => 'IP&nbsp;Address',
381                            attrib  => 'Framed-IP-Address',
382                            fmt     => sub { my $ip = shift;
383                                             length($ip) ? $ip : '&nbsp';
384                                           },
385                            align   => 'right',
386                          },
387   'acctstarttime'     => {
388                            name    => 'Start&nbsp;time',
389                            attrib  => 'Acct-Start-Time',
390                            fmt     => $time_format,
391                            align   => 'left',
392                          },
393   'acctstoptime'      => {
394                            name    => 'End&nbsp;time',
395                            attrib  => 'Acct-Stop-Time',
396                            fmt     => $time_format_or_open,
397                            align   => 'left',
398                          },
399   'acctsessiontime'   => {
400                            name    => 'Duration',
401                            attrib  => 'Acct-Session-Time',
402                            fmt     => $duration_format,
403                            align   => 'right',
404                          },
405   'acctinputoctets'   => {
406                            name    => 'Upload', # (from user)',
407                            attrib  => 'Acct-Input-Octets',
408                            fmt     => $octets_format,
409                            align   => 'right',
410                          },
411   'acctoutputoctets'  => {
412                            name    => 'Download', # (to user)',
413                            attrib  => 'Acct-Output-Octets',
414                            fmt     => $octets_format,
415                            align   => 'right',
416                          },
417 ;
418 }
419 $fields{$_}->{fmt} ||= sub { length($_[0]) ? shift : '&nbsp'; }
420   foreach keys %fields;
421
422 </%init>