From: ivan Date: Mon, 18 May 2009 09:55:30 +0000 (+0000) Subject: basic CDR viewing from self-service, RT#4018 X-Git-Tag: root_of_svc_elec_features~1192 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=aab3bdd971c21f6d422b7708ecf8ba7cb5ec0fea basic CDR viewing from self-service, RT#4018 --- diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm index d64c72c0e..ab5096891 100644 --- a/FS/FS/ClientAPI/MyAccount.pm +++ b/FS/FS/ClientAPI/MyAccount.pm @@ -10,7 +10,7 @@ use Business::CreditCard; use Time::Duration; use FS::UI::Web::small_custview qw(small_custview); #less doh use FS::UI::Web; -use FS::UI::bytecount; +use FS::UI::bytecount qw( display_bytecount ); use FS::Conf; use FS::Record qw(qsearch qsearchs); use FS::Msgcat qw(gettext); @@ -772,8 +772,14 @@ sub list_svcs { : $cust_main->unsuspended_pkgs ) { push @cust_svc, @{[ $cust_pkg->cust_svc ]}; #@{[ ]} to force array context } - @cust_svc = grep { $_->part_svc->svcdb eq $p->{'svcdb'} } @cust_svc - if $p->{'svcdb'}; + if ( $p->{'svcdb'} ) { + my $svcdb = ref($p->{'svcdb'}) eq 'HASH' + ? $p->{'svcdb'} + : ref($p->{'svcdb'}) eq 'ARRAY' + ? { map { $_=>1 } @{ $p->{'svcdb'} } } + : { $p->{'svcdb'} => 1 }; + @cust_svc = grep $svcdb->{ $_->part_svc->svcdb }, @cust_svc + } #@svc_x = sort { $a->domain cmp $b->domain || $a->username cmp $b->username } # @svc_x; @@ -781,30 +787,51 @@ sub list_svcs { { #no#'svcnum' => $session->{'svcnum'}, 'custnum' => $custnum, - 'svcs' => [ map { - my $svc_x = $_->svc_x; - my($label, $value) = $_->label; - my $part_pkg = $svc_x->cust_svc->cust_pkg->part_pkg; - - { 'svcnum' => $_->svcnum, - 'label' => $label, - 'value' => $value, - 'username' => $svc_x->username, - 'email' => $svc_x->email, - 'seconds' => $svc_x->seconds, - 'upbytes' => FS::UI::bytecount::display_bytecount($svc_x->upbytes), - 'downbytes' => FS::UI::bytecount::display_bytecount($svc_x->downbytes), - 'totalbytes'=> FS::UI::bytecount::display_bytecount($svc_x->totalbytes), - 'recharge_amount' => $part_pkg->option('recharge_amount', 1), - 'recharge_seconds' => $part_pkg->option('recharge_seconds', 1), - 'recharge_upbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_upbytes', 1)), - 'recharge_downbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_downbytes', 1)), - 'recharge_totalbytes' => FS::UI::bytecount::display_bytecount($part_pkg->option('recharge_totalbytes', 1)), - # more... - }; - } - @cust_svc - ], + 'svcs' => [ + map { + my $svc_x = $_->svc_x; + my($label, $value) = $_->label; + my $svcdb = $_->part_svc->svcdb; + my $part_pkg = $_->cust_pkg->part_pkg; + + my %hash = ( + 'svcnum' => $_->svcnum, + 'svcdb' => $svcdb, + 'label' => $label, + 'value' => $value, + ); + + if ( $svcdb eq 'svc_acct' ) { + %hash = ( + %hash, + 'username' => $svc_x->username, + 'email' => $svc_x->email, + 'seconds' => $svc_x->seconds, + 'upbytes' => display_bytecount($svc_x->upbytes), + 'downbytes' => display_bytecount($svc_x->downbytes), + 'totalbytes' => display_bytecount($svc_x->totalbytes), + + 'recharge_amount' => $part_pkg->option('recharge_amount',1), + 'recharge_seconds' => $part_pkg->option('recharge_seconds',1), + 'recharge_upbytes' => + display_bytecount($part_pkg->option('recharge_upbytes',1)), + 'recharge_downbytes' => + display_bytecount($part_pkg->option('recharge_downbytes',1)), + 'recharge_totalbytes' => + display_bytecount($part_pkg->option('recharge_totalbytes',1)), + # more... + ); + + } elsif ( $svcdb eq 'svc_phone' ) { + %hash = ( + %hash, + ); + } + + \%hash; + } + @cust_svc + ], }; } @@ -814,9 +841,8 @@ sub _list_svc_usage { my @usage = (); foreach my $part_export ( map { qsearch ( 'part_export', { 'exporttype' => $_ } ) } - qw (sqlradius sqlradius_withdomain') + qw( sqlradius sqlradius_withdomain ) ) { - push @usage, @ { $part_export->usage_sessions($begin, $end, $svc_acct) }; } (@usage); @@ -849,29 +875,50 @@ sub list_support_usage { _usage_details(\&_list_support_usage, @_); } +sub _list_cdr_usage { + my($svc_phone, $begin, $end) = @_; + map [ $_->downstream_csv('format' => 'default') ], #XXX config for format + $svc_phone->cust_svc->get_cdrs( 'begin'=>$begin, 'end'=>$end, ); +} + +sub list_cdr_usage { + my $p = shift; + _usage_details( \&_list_cdr_usage, $p, + 'svcdb' => 'svc_phone', + ); +} + sub _usage_details { - my ($callback, $p) = (shift,shift); + my($callback, $p, %opt) = @_; my($context, $session, $custnum) = _custoragent_session_custnum($p); return { 'error' => $session } if $context eq 'error'; my $search = { 'svcnum' => $p->{'svcnum'} }; $search->{'agentnum'} = $session->{'agentnum'} if $context eq 'agent'; - my $svc_acct = qsearchs ( 'svc_acct', $search ); + + my $svcdb = $opt{'svcdb'} || 'svc_acct'; + + my $svc_x = qsearchs( $svcdb, $search ); return { 'error' => 'No service selected in list_svc_usage' } - unless $svc_acct; + unless $svc_x; - my $freq = $svc_acct->cust_svc->cust_pkg->part_pkg->freq; - my $start = $svc_acct->cust_svc->cust_pkg->setup; - #my $end = $svc_acct->cust_svc->cust_pkg->bill; # or time? - my $end = time; + my $header = $svcdb eq 'svc_phone' + ? [ split(',', FS::cdr::invoice_header('default') ) ] #XXX + : []; - unless($p->{beginning}){ - $p->{beginning} = $svc_acct->cust_svc->cust_pkg->last_bill; - $p->{ending} = $end; + my $cust_pkg = $svc_x->cust_svc->cust_pkg; + my $freq = $cust_pkg->part_pkg->freq; + my $start = $cust_pkg->setup; + #my $end = $cust_pkg->bill; # or time? + my $end = time; + + unless ( $p->{beginning} ) { + $p->{beginning} = $cust_pkg->last_bill; + $p->{ending} = $end; } - my (@usage) = &$callback($svc_acct,$p->{beginning},$p->{ending}); + my (@usage) = &$callback($svc_x, $p->{beginning}, $p->{ending}); #kinda false laziness with FS::cust_main::bill, but perhaps #we should really change this bit to DateTime and DateTime::Duration @@ -914,6 +961,7 @@ sub _usage_details { 'ending' => $p->{ending}, 'previous' => ($previous > $start) ? $previous : $start, 'next' => ($next < $end) ? $next : $end, + 'header' => $header, 'usage' => \@usage, }; } diff --git a/FS/FS/UI/bytecount.pm b/FS/FS/UI/bytecount.pm index 0ddc7545c..7e78bf501 100644 --- a/FS/FS/UI/bytecount.pm +++ b/FS/FS/UI/bytecount.pm @@ -1,10 +1,15 @@ package FS::UI::bytecount; use strict; -use vars qw($DEBUG $me); +use vars qw($DEBUG $me @ISA @EXPORT_OK); +use Exporter; use FS::Conf; use Number::Format 1.50; +@ISA = qw( Exporter ); + +@EXPORT_OK = qw( bytecount_unexact parse_bytecount display_bytecount ); + $DEBUG = 0; $me = '[FS::UID::bytecount]'; diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index c4a75f77a..fe831381f 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -692,32 +692,56 @@ CDRs are associated with svc_phone services via svc_phone.phonenum =cut sub get_cdrs_for_update { + my $self = shift; + $self->get_cdrs( 'freesidestatus' => '', + 'for_update' => 1, + @_, + ); +} + +sub get_cdrs { my($self, %options) = @_; my @fields = ( 'charged_party' ); push @fields, 'src' unless $options{'disable_src'}; - #CDRs are now associated with svc_phone services via svc_phone.phonenum + my $for_update = $options{'for_update'} ? 'FOR UPDATE' : ''; + + my %hash = (); + $hash{'freesidestatus'} = $options{'freesidestatus'} + if exists($options{'freesidestatus'}); + + #CDRs are associated with svc_phone services via svc_phone.phonenum + #return () unless $self->svc_x->isa('FS::svc_phone'); return () unless $self->part_svc->svcdb eq 'svc_phone'; my $number = $self->svc_x->phonenum; my $prefix = $options{'default_prefix'}; - my @where = map " $_ = '$number' ", @fields; - push @where, map " $_ = '$prefix$number' ", @fields + my @orwhere = map " $_ = '$number' ", @fields; + push @orwhere, map " $_ = '$prefix$number' ", @fields if length($prefix); if ( $prefix =~ /^\+(\d+)$/ ) { - push @where, map " $_ = '$1$number' ", @fields + push @orwhere, map " $_ = '$1$number' ", @fields + } + + my @where = ( ' ( '. join(' OR ', @orwhere ). ' ) ' ); + + if ( $options{'begin'} ) { + push @where, 'startdate >= '. $options{'begin'}; + } + if ( $options{'end'} ) { + push @where, 'startdate < '. $options{'end'}; } - my $extra_sql = ' AND ( '. join(' OR ', @where ). ' ) '; + my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where ); my @cdrs = qsearch( { 'table' => 'cdr', - 'hashref' => { 'freesidestatus' => '', }, - 'extra_sql' => "$extra_sql FOR UPDATE", + 'hashref' => \%hash, + 'extra_sql' => "$extra_sql $for_update", } ); @cdrs; diff --git a/fs_selfservice/FS-SelfService/SelfService.pm b/fs_selfservice/FS-SelfService/SelfService.pm index fef211580..47f312ac0 100644 --- a/fs_selfservice/FS-SelfService/SelfService.pm +++ b/fs_selfservice/FS-SelfService/SelfService.pm @@ -45,6 +45,7 @@ $socket .= '.'.$tag if defined $tag && length($tag); 'list_pkgs' => 'MyAccount/list_pkgs', #add to ss (added?) 'list_svcs' => 'MyAccount/list_svcs', #add to ss (added?) 'list_svc_usage' => 'MyAccount/list_svc_usage', + 'list_cdr_usage' => 'MyAccount/list_cdr_usage', 'list_support_usage' => 'MyAccount/list_support_usage', 'order_pkg' => 'MyAccount/order_pkg', #add to ss cgi! 'change_pkg' => 'MyAccount/change_pkg', diff --git a/fs_selfservice/FS-SelfService/cgi/header.html b/fs_selfservice/FS-SelfService/cgi/header.html new file mode 100644 index 000000000..cf8fd2bd9 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/header.html @@ -0,0 +1,9 @@ + + + MyAccount + + + MyAccount +

+ <%= include('myaccount_menu') %> + diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi index bb3db12c6..ecf2553a3 100644 --- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi +++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi @@ -15,7 +15,8 @@ use FS::SelfService qw( login_info login customer_info edit_info invoice list_pkgs order_pkg signup_info order_recharge part_svc_info provision_acct provision_external unprovision_svc change_pkg domainselector - list_svcs list_svc_usage list_support_usage + list_svcs + list_svc_usage list_cdr_usage list_support_usage myaccount_passwd ); @@ -72,7 +73,7 @@ $session_id = $cgi->param('session'); #order|pw_list XXX ??? $cgi->param('action') =~ - /^(myaccount|view_invoice|make_payment|make_ach_payment|make_thirdparty_payment|payment_results|ach_payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|change_pay|process_change_bill|process_change_ship|process_change_pay|customer_order_pkg|process_order_pkg|customer_change_pkg|process_change_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage|view_usage_details|view_support_details|change_password|process_change_password)$/ + /^(myaccount|view_invoice|make_payment|make_ach_payment|make_thirdparty_payment|payment_results|ach_payment_results|recharge_prepay|recharge_results|logout|change_bill|change_ship|change_pay|process_change_bill|process_change_ship|process_change_pay|customer_order_pkg|process_order_pkg|customer_change_pkg|process_change_pkg|process_order_recharge|provision|provision_svc|process_svc_acct|process_svc_external|delete_svc|view_usage|view_usage_details|view_cdr_details|view_support_details|change_password|process_change_password)$/ or die "unknown action ". $cgi->param('action'); my $action = $1; @@ -564,7 +565,7 @@ sub delete_svc { sub view_usage { list_svcs( 'session_id' => $session_id, - 'svcdb' => 'svc_acct', + 'svcdb' => [ 'svc_acct', 'svc_phone' ], 'ncancelled' => 1, ); } @@ -578,6 +579,15 @@ sub view_usage_details { ); } +sub view_cdr_details { + list_cdr_usage( + 'session_id' => $session_id, + 'svcnum' => $cgi->param('svcnum'), + 'beginning' => $cgi->param('beginning') || '', + 'ending' => $cgi->param('ending') || '', + ); +} + sub view_support_details { list_support_usage( 'session_id' => $session_id, diff --git a/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html b/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html new file mode 100644 index 000000000..32bd632b4 --- /dev/null +++ b/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html @@ -0,0 +1,54 @@ +<%= $url = "$selfurl?session=$session_id;action="; ''; %> +<%= include('header') %> + +Call usage for +<%= Date::Format::time2str('%b %o %Y', $beginning) %> - +<%= Date::Format::time2str('%b %o %Y', $ending) %> +

+ +<%= if ( $error ) { + $OUT .= qq!$error

!; +} ''; %> + + + + + + +
+<%= if ($previous < $beginning) { + $OUT .= qq!Previous period!; + }else{ + ''; + } %> + +<%= if ($next > $ending) { + $OUT .= qq!Next period!; + }else{ + ''; + }%> +
+ + +<%= foreach my $header (@header) { + $OUT .= qq(); + } +%> + +<%= my $total = 0; + my $utotal = 0; + my $dtotal = 0; + foreach my $usage ( @usage ) { + $OUT .= ''; + $OUT .= qq() foreach @{$usage}; + $OUT .= ''; + } +%> + +
$header
$_
+
+ + +<%= include('footer') %> diff --git a/fs_selfservice/FS-SelfService/cgi/view_usage.html b/fs_selfservice/FS-SelfService/cgi/view_usage.html index b78f9975b..b492102ce 100644 --- a/fs_selfservice/FS-SelfService/cgi/view_usage.html +++ b/fs_selfservice/FS-SelfService/cgi/view_usage.html @@ -1,24 +1,30 @@ -MyAccount -MyAccount

-<%= $url = "$selfurl?session=$session_id;action="; ''; %> -<%= include('myaccount_menu') %> - - -Service usage

+<%= $url = "$selfurl?session=$session_id;action="; + @svc_acct = grep { $_->{svcdb} eq 'svc_acct' } @svcs; + @svc_phone = grep { $_->{svcdb} eq 'svc_phone' } @svcs; + ''; +%> +<%= include('header') %> <%= if ( $error ) { $OUT .= qq!$error

!; } ''; %> - - - - - - - - -<%= foreach my $svc ( @svcs ) { +<%= if ( @svc_acct ) { + $OUT.= 'Account usage

+
AccountTime remainingUpload remainingDownload remainingTotal remaining
+ + + + + + + '; + } else { + $OUT .= ''; + } +%> + +<%= foreach my $svc ( @svc_acct ) { my $link = "${url}view_usage_details;". "svcnum=$svc->{'svcnum'};beginning=0;ending=0"; $OUT .= ''; } - } %> + } +%> -
AccountTime remainingUpload remainingDownload remainingTotal remaining
'; @@ -48,11 +54,33 @@ $OUT .= $svc->{'recharge_totalbytes'} if $svc->{'recharge_totalbytes'}; $OUT .= '
-
+<%= scalar(@svc_acct) ? '

' : '' %> - +<%= if ( @svc_phone ) { + $OUT.= 'Call usage

+ + + '; #"Account" ? + #what else? + $OUT .= ''; + } else { + $OUT .= ''; + } +%> +<%= foreach my $svc_phone ( @svc_phone ) { + my $link = "${url}view_cdr_details;". + "svcnum=$svc_phone->{'svcnum'};beginning=0;ending=0"; + $OUT .= ''; + } +%> + +<%= scalar(@svc_phone) ? '
Number
'; + $OUT .= qq!!. $svc_phone->{'label'}. ': '. $svc_phone->{'value'}.''; + $OUT .= '


' : '' %> + + <%= include('footer') %>