From: Ivan Kohler Date: Sat, 17 Jan 2015 02:37:43 +0000 (-0800) Subject: Merge branch 'master' of git.freeside.biz:/home/git/freeside X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=b7cf1606a66cca95e3540f803ffa66d223f23a40;hp=-c Merge branch 'master' of git.freeside.biz:/home/git/freeside --- b7cf1606a66cca95e3540f803ffa66d223f23a40 diff --combined FS/FS/part_pkg/voip_cdr.pm index f007029d6,e3fdd79ff..205335b7e --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@@ -19,6 -19,7 +19,7 @@@ tie my %cdr_svc_method, 'Tie::IxHash' 'svc_pbx.svcnum' => 'Freeside service # (svc_pbx.svcnum)', 'svc_pbx.ip.src' => 'PBX name to source IP address', 'svc_pbx.ip.dst' => 'PBX name to destination IP address', + 'svc_acct.username' => 'Username (svc_acct.username)', ; tie my %rating_method, 'Tie::IxHash', @@@ -463,16 -464,20 +464,20 @@@ sub calc_usage #my @invoice_details_sort; # for tagging invoice details + # (unfortunate; should be a svc_x class method or table_info item or + # something) my $phonenum; if ( $svc_table eq 'svc_phone' ) { $phonenum = $svc_x->phonenum; } elsif ( $svc_table eq 'svc_pbx' ) { $phonenum = $svc_x->title; + } elsif ( $svc_table eq 'svc_acct' ) { + $phonenum = $svc_x->username; } $formatter->phonenum($phonenum); #first rate any outstanding CDRs not yet rated - # XXX eventually use an FS::Cursor for this + # use FS::Cursor for this starting in 4.x my $cdr_search = $svc_x->psearch_cdrs(%options); $cdr_search->limit(1000); $cdr_search->increment(0); # because we're changing their status as we go @@@ -678,7 -683,6 +683,7 @@@ sub reset_usage # tells whether cust_bill_pkg_detail should return a single line for # each phonenum +# i think this is currently unused? sub sum_usage { my $self = shift; $self->option('output_format') =~ /^sum_/; diff --combined FS/FS/svc_acct.pm index 94eec0c83,62d7b877c..452f250d8 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@@ -40,6 -40,7 +40,7 @@@ use FS::Record qw( qsearch qsearchs fie use FS::Msgcat qw(gettext); use FS::UI::bytecount; use FS::UI::Web; + use FS::PagedSearch qw( psearch ); # XXX in v4, replace with FS::Cursor use FS::part_pkg; use FS::part_svc; use FS::svc_acct_pop; @@@ -293,21 -294,25 +294,21 @@@ sub table_info label => 'Quota', #Mail storage limit type => 'text', disable_inventory => 1, - disable_select => 1, }, 'file_quota'=> { label => 'File storage limit', type => 'text', disable_inventory => 1, - disable_select => 1, }, 'file_maxnum'=> { label => 'Number of files limit', type => 'text', disable_inventory => 1, - disable_select => 1, }, 'file_maxsize'=> { label => 'File size limit', type => 'text', disable_inventory => 1, - disable_select => 1, }, '_password' => 'Password', 'gid' => { @@@ -2367,65 -2372,94 +2368,94 @@@ sub last_login_text $self->last_login ? ctime($self->last_login) : 'unknown'; } - =item get_cdrs TIMESTAMP_START TIMESTAMP_END [ 'OPTION' => 'VALUE ... ] + =item psearch_cdrs OPTIONS + + Returns a paged search (L) for Call Detail Records + associated with this service. For svc_acct, "associated with" means that + either the "src" or the "charged_party" field of the CDR matches the + "username" field of the service. =cut - sub get_cdrs { - my($self, $start, $end, %opt ) = @_; - - my $did = $self->username; #yup - - my $prefix = $opt{'default_prefix'}; #convergent.au '+61' - - my $for_update = $opt{'for_update'} ? 'FOR UPDATE' : ''; - - #SELECT $for_update * FROM cdr - # WHERE calldate >= $start #need a conversion - # AND calldate < $end #ditto - # AND ( charged_party = "$did" - # OR charged_party = "$prefix$did" #if length($prefix); - # OR ( ( charged_party IS NULL OR charged_party = '' ) - # AND - # ( src = "$did" OR src = "$prefix$did" ) # if length($prefix) - # ) - # ) - # AND ( freesidestatus IS NULL OR freesidestatus = '' ) - - my $charged_or_src; - if ( length($prefix) ) { - $charged_or_src = - " AND ( charged_party = '$did' - OR charged_party = '$prefix$did' - OR ( ( charged_party IS NULL OR charged_party = '' ) - AND - ( src = '$did' OR src = '$prefix$did' ) - ) - ) - "; - } else { - $charged_or_src = - " AND ( charged_party = '$did' - OR ( ( charged_party IS NULL OR charged_party = '' ) - AND - src = '$did' - ) - ) - "; + sub psearch_cdrs { + my($self, %options) = @_; + my @fields; + my %hash; + my @where; + + my $did = dbh->quote($self->username); + + my $prefix = $options{'default_prefix'} || ''; #convergent.au '+61' + my $prefixdid = dbh->quote($prefix . $self->username); + + my $for_update = $options{'for_update'} ? 'FOR UPDATE' : ''; + if ( $options{inbound} ) { + # these will be selected under their DIDs + push @where, "FALSE"; } - qsearch( - 'select' => "$for_update *", + my @orwhere; + if (!$options{'disable_charged_party'}) { + push @orwhere, + "charged_party = $did", + "charged_party = $prefixdid"; + } + if (!$options{'disable_src'}) { + push @orwhere, + "src = $did AND charged_party IS NULL", + "src = $prefixdid AND charged_party IS NULL"; + } + push @where, '(' . join(' OR ', @orwhere) . ')'; + + # $options{'status'} = '' is meaningful; for the rest of them it's not + if ( exists $options{'status'} ) { + $hash{'freesidestatus'} = $options{'status'}; + } + if ( $options{'cdrtypenum'} ) { + $hash{'cdrtypenum'} = $options{'cdrtypenum'}; + } + if ( $options{'calltypenum'} ) { + $hash{'calltypenum'} = $options{'calltypenum'}; + } + if ( $options{'begin'} ) { + push @where, 'startdate >= '. $options{'begin'}; + } + if ( $options{'end'} ) { + push @where, 'startdate < '. $options{'end'}; + } + if ( $options{'nonzero'} ) { + push @where, 'duration > 0'; + } + + my $extra_sql = join(' AND ', @where); + if ($extra_sql) { + if (keys %hash) { + $extra_sql = " AND ".$extra_sql; + } else { + $extra_sql = " WHERE ".$extra_sql; + } + } + return psearch({ + 'select' => '*', 'table' => 'cdr', - 'hashref' => { - #( freesidestatus IS NULL OR freesidestatus = '' ) - 'freesidestatus' => '', - }, - 'extra_sql' => $charged_or_src, + 'hashref' => \%hash, + 'extra_sql' => $extra_sql, + 'order_by' => "ORDER BY startdate $for_update", + }); + } - ); + =item get_cdrs (DEPRECATED) + Like psearch_cdrs, but returns all the L objects at once, in a + single list. Arguments are the same as for psearch_cdrs. + + =cut + + sub get_cdrs { + my $self = shift; + my $psearch = $self->psearch_cdrs(@_); + qsearch ( $psearch->{query} ) } # sub radius_groups has moved to svc_Radius_Mixin