[freeside-commits] branch FREESIDE_2_3_BRANCH updated. d5c51ff8d85f1f9ad64961878dcba6adb7968523
Mark Wells
mark at 420.am
Tue Mar 5 16:51:00 PST 2013
The branch, FREESIDE_2_3_BRANCH has been updated
via d5c51ff8d85f1f9ad64961878dcba6adb7968523 (commit)
from ede90e4c0ff771538dfe184c10d8fb1a3f2bb469 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit d5c51ff8d85f1f9ad64961878dcba6adb7968523
Author: Mark Wells <mark at freeside.biz>
Date: Tue Mar 5 16:47:48 2013 -0800
display inbound CDRs in selfservice, #18316; Taqua caller ID, #18574
diff --git a/FS/FS/ClientAPI/MyAccount.pm b/FS/FS/ClientAPI/MyAccount.pm
index f949246..be87e59 100644
--- a/FS/FS/ClientAPI/MyAccount.pm
+++ b/FS/FS/ClientAPI/MyAccount.pm
@@ -1692,7 +1692,34 @@ sub list_svcs {
} else {
$hash{'name'} = $cust_main->name;
}
+ } elsif ( $svcdb eq 'svc_phone' ) {
+ # could potentially show lots of things...
+ $hash{'outbound'} = 1;
+ $hash{'inbound'} = 0;
+ if ( $part_pkg->plan eq 'voip_inbound' ) {
+ $hash{'outbound'} = 0;
+ $hash{'inbound'} = 1;
+ } elsif ( $part_pkg->option('selfservice_inbound_format')
+ or $conf->config('selfservice-default_inbound_cdr_format')
+ ) {
+ $hash{'inbound'} = 1;
+ }
+ foreach (qw(inbound outbound)) {
+ # hmm...we can't filter by status here, because there might
+ # not be cdr_terminations at all. have to go by date.
+ # find all since the last bill date.
+ # XXX cdr types? we are going to need them.
+ if ( $hash{$_} ) {
+ my $sum_cdr = $svc_x->sum_cdrs(
+ 'inbound' => ( $_ eq 'inbound' ? 1 : 0 ),
+ 'begin' => ($cust_pkg->last_bill || 0),
+ 'nonzero' => 1,
+ );
+ $hash{$_} = $sum_cdr->hashref;
+ }
+ }
}
+
# elsif ( $svcdb eq 'svc_phone' || $svcdb eq 'svc_port' ) {
# %hash = (
# %hash,
@@ -1963,7 +1990,7 @@ sub _list_cdr_usage {
# XXX CDR type support...
my($svc_phone, $begin, $end, %opt) = @_;
map [ $_->downstream_csv(%opt, 'keeparray' => 1) ],
- $svc_phone->get_cdrs( 'begin'=>$begin, 'end'=>$end, );
+ $svc_phone->get_cdrs( 'begin'=>$begin, 'end'=>$end, %opt );
}
sub list_cdr_usage {
@@ -1993,18 +2020,21 @@ sub _usage_details {
my %callback_opt;
my $header = [];
if ( $svcdb eq 'svc_phone' ) {
- my $format = $cust_pkg->part_pkg->option('output_format') || '';
- $format = '' if $format =~ /^sum_/;
- # sensible default if there is no format or it's a summary format
- if ( $cust_pkg->part_pkg->plan eq 'voip_inbound' ) {
- $format ||= 'source_default';
+ my $conf = FS::Conf->new;
+ my $format = '';
+ if ( $p->{inbound} ) {
+ $format = $cust_pkg->part_pkg->option('selfservice_inbound_format')
+ || $conf->config('selfservice-default_inbound_cdr_format')
+ || 'source_default';
$callback_opt{inbound} = 1;
+ } else {
+ $format = $cust_pkg->part_pkg->option('selfservice_format')
+ || $conf->config('selfservice-default_cdr_format')
+ || 'default';
}
- else {
- $format ||= 'default';
- }
-
+
$callback_opt{format} = $format;
+ $callback_opt{use_clid} = 1;
$header = [ split(',', FS::cdr::invoice_header($format) ) ];
}
@@ -2063,6 +2093,7 @@ sub _usage_details {
'svcnum' => $p->{svcnum},
'beginning' => $p->{beginning},
'ending' => $p->{ending},
+ 'inbound' => $p->{inbound},
'previous' => ($previous > $start) ? $previous : $start,
'next' => ($next < $end) ? $next : $end,
'header' => $header,
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm
index c0c7c03..2b9f7b9 100644
--- a/FS/FS/Conf.pm
+++ b/FS/FS/Conf.pm
@@ -710,6 +710,18 @@ my %payment_gateway_options = (
},
);
+my @cdr_formats = (
+ '' => '',
+ 'default' => 'Default',
+ 'source_default' => 'Default with source',
+ 'accountcode_default' => 'Default plus accountcode',
+ 'description_default' => 'Default with description field as destination',
+ 'basic' => 'Basic',
+ 'simple' => 'Simple',
+ 'simple2' => 'Simple with source',
+ 'accountcode_simple' => 'Simple with accountcode',
+);
+
#Billing (81 items)
#Invoicing (50 items)
#UI (69 items)
@@ -4628,6 +4640,13 @@ and customer address. Include units.',
},
{
+ 'key' => 'cdr-taqua-callerid_rewrite',
+ 'section' => 'telephony',
+ 'description' => 'For the Taqua CDR format, pull Caller ID blocking information from secondary CDRs.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'cust_pkg-show_autosuspend',
'section' => 'UI',
'description' => 'Show package auto-suspend dates. Use with caution for now; can slow down customer view for large insallations.',
@@ -5199,6 +5218,22 @@ and customer address. Include units.',
},
{
+ 'key' => 'selfservice-default_cdr_format',
+ 'section' => 'self-service',
+ 'description' => 'Format for showing outbound CDRs in self-service. The per-package option overrides this.',
+ 'type' => 'select',
+ 'select_hash' => \@cdr_formats,
+ },
+
+ {
+ 'key' => 'selfservice-default_inbound_cdr_format',
+ 'section' => 'self-service',
+ 'description' => 'Format for showing inbound CDRs in self-service. The per-package option overrides this. Leave blank to avoid showing these CDRs.',
+ 'type' => 'select',
+ 'select_hash' => \@cdr_formats,
+ },
+
+ {
'key' => 'logout-timeout',
'section' => 'UI',
'description' => 'If set, automatically log users out of the backoffice after this many minutes.',
diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index 3e89f55..bf7a907 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -630,6 +630,8 @@ sub export_formats {
length($price) ? ($opt{money_char} . $price) : '';
};
+ my $src_sub = sub { $_[0]->clid || $_[0]->src };
+
%export_formats = (
'simple' => [
sub { time2str($date_format, shift->calldate_unix ) }, #DATE
@@ -644,7 +646,7 @@ sub export_formats {
sub { time2str($date_format, shift->calldate_unix ) }, #DATE
sub { time2str('%r', shift->calldate_unix ) }, #TIME
#'userfield', #USER
- 'src', #called from
+ $src_sub, #called from
'dst', #NUMBER_DIALED
$duration_sub, #DURATION
#sub { sprintf('%.3f', shift->upstream_price ) }, #PRICE
@@ -653,7 +655,7 @@ sub export_formats {
'accountcode_simple' => [
sub { time2str($date_format, shift->calldate_unix ) }, #DATE
sub { time2str('%r', shift->calldate_unix ) }, #TIME
- 'src', #called from
+ $src_sub, #called from
'accountcode', #NUMBER_DIALED
$duration_sub, #DURATION
$price_sub,
@@ -661,14 +663,14 @@ sub export_formats {
'sum_duration' => [
# for summary formats, the CDR is a fictitious object containing the
# total billsec and the phone number of the service
- 'src',
+ $src_sub,
sub { my($cdr, %opt) = @_; $opt{ratename} },
sub { my($cdr, %opt) = @_; $opt{count} },
sub { my($cdr, %opt) = @_; int($opt{seconds}/60).'m' },
$price_sub,
],
'sum_count' => [
- 'src',
+ $src_sub,
sub { my($cdr, %opt) = @_; $opt{ratename} },
sub { my($cdr, %opt) = @_; $opt{count} },
$price_sub,
@@ -702,7 +704,7 @@ sub export_formats {
$price_sub,
],
);
- $export_formats{'source_default'} = [ 'src', @{ $export_formats{'default'} }, ];
+ $export_formats{'source_default'} = [ $src_sub, @{ $export_formats{'default'} }, ];
$export_formats{'accountcode_default'} =
[ @{ $export_formats{'default'} }[0,1],
'accountcode',
@@ -710,7 +712,7 @@ sub export_formats {
];
my @default = @{ $export_formats{'default'} };
$export_formats{'description_default'} =
- [ 'src', @default[0..2],
+ [ $src_sub, @default[0..2],
sub { my($cdr, %opt) = @_; $cdr->description },
@default[4,5] ];
diff --git a/FS/FS/cdr/taqua62.pm b/FS/FS/cdr/taqua62.pm
index 862018e..aa94630 100644
--- a/FS/FS/cdr/taqua62.pm
+++ b/FS/FS/cdr/taqua62.pm
@@ -20,7 +20,9 @@ use FS::cdr qw(_cdr_date_parser_maker);
my($cdr, $field, $conf, $hashref) = @_;
$hashref->{skiprow} = 1
unless ($field == 0 && $cdr->disposition == 100 ) #regular CDR
- || ($field == 1 && $cdr->lastapp eq 'acctcode'); #accountcode
+ || ($field == 1 && $cdr->lastapp eq 'acctcode') #accountcode
+ || ($field == 1 && $cdr->lastapp eq 'CallerId') #CID blocking
+ ;
$cdr->cdrtypenum($field);
},
diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm
index 73b0aed..9943cfc 100644
--- a/FS/FS/part_pkg/voip_cdr.pm
+++ b/FS/FS/part_pkg/voip_cdr.pm
@@ -49,6 +49,11 @@ tie my %unrateable_opts, 'Tie::IxHash',
2 => 'Flag for later review',
;
+tie my %detail_formats, 'Tie::IxHash',
+ '' => '',
+ FS::cdr::invoice_formats()
+;
+
%info = (
'name' => 'VoIP rating by plan of CDR records in an internal (or external) SQL table',
'shortname' => 'VoIP/telco CDR rating (standard)',
@@ -206,12 +211,25 @@ tie my %unrateable_opts, 'Tie::IxHash',
},
#false laziness w/cdr_termination.pm
- 'output_format' => { 'name' => 'CDR invoice display format',
+ 'output_format' => { 'name' => 'CDR display format for invoices',
'type' => 'select',
- 'select_options' => { FS::cdr::invoice_formats() },
+ 'select_options' => \%detail_formats,
'default' => 'default', #XXX test
},
+ 'selfservice_format' =>
+ { 'name' => 'CDR display format for selfservice',
+ 'type' => 'select',
+ 'select_options' => \%detail_formats,
+ 'default' => 'default'
+ },
+ 'selfservice_inbound_format' =>
+ { 'name' => 'Inbound CDR display format for selfservice',
+ 'type' => 'select',
+ 'select_options' => \%detail_formats,
+ 'default' => ''
+ },
+
'usage_section' => { 'name' => 'Section in which to place usage charges (whether separated or not): ',
},
@@ -287,7 +305,9 @@ tie my %unrateable_opts, 'Tie::IxHash',
skip_max_callers
use_duration
411_rewrite
- output_format usage_mandate summarize_usage usage_section
+ output_format
+ selfservice_format selfservice_inbound_format
+ usage_mandate summarize_usage usage_section
bill_every_call bill_inactive_svcs
count_available_phones suspend_bill
)
diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm
index 118748e..097310b 100644
--- a/FS/FS/svc_phone.pm
+++ b/FS/FS/svc_phone.pm
@@ -673,13 +673,15 @@ with the chosen prefix.
=item disable_src => 1: Only match on "charged_party", not "src".
+=item nonzero: Only return CDRs where duration > 0.
+
=item by_svcnum: not supported for svc_phone
=back
=cut
-sub get_cdrs {
+sub _search_cdrs { # transitional; replaced with psearch_cdrs in 3.0
my($self, %options) = @_;
my @fields;
my %hash;
@@ -735,19 +737,48 @@ sub get_cdrs {
if ( $options{'end'} ) {
push @where, 'startdate < '. $options{'end'};
}
+ if ( $options{'nonzero'} ) {
+ push @where, 'duration > 0';
+ }
my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where );
- my @cdrs =
- qsearch( {
+
+ return {
'table' => 'cdr',
'hashref' => \%hash,
'extra_sql' => $extra_sql,
'order_by' => $options{'billsec_sum'} ? '' : "ORDER BY startdate $for_update",
'select' => $options{'billsec_sum'} ? 'sum(billsec) as billsec_sum' : '*',
- } );
+ };
+}
- @cdrs;
+sub get_cdrs {
+ qsearch(_search_cdrs(@_));
+}
+
+=item sum_cdrs
+
+Takes the same options as psearch_cdrs, but returns a single row containing
+"count" (the number of CDRs) and the sums of the following fields: duration,
+billsec, rated_price, rated_seconds, rated_minutes.
+
+Note that if any calls are not rated, their rated_* fields will be null.
+If you want to use those fields, pass the 'status' option to limit to
+calls that have been rated. This is intentional; please don't "fix" it.
+
+=cut
+
+sub sum_cdrs {
+ my $self = shift;
+ my $search = $self->_search_cdrs(@_);
+ $search->{'select'} = join(',',
+ 'COUNT(*) AS count',
+ map { "SUM($_) AS $_" }
+ qw(duration billsec rated_price rated_seconds rated_minutes)
+ );
+ $search->{'order_by'} = '';
+ qsearchs ( $search );
}
=back
diff --git a/FS/bin/freeside-cdrrewrited b/FS/bin/freeside-cdrrewrited
index 846b0b9..482e849 100644
--- a/FS/bin/freeside-cdrrewrited
+++ b/FS/bin/freeside-cdrrewrited
@@ -30,9 +30,9 @@ die "not running; cdr-asterisk_forward_rewrite, cdr-charged_party_rewrite ".
#--
-my %accountcode_unmatch = ();
-my $accountcode_retry = 4 * 60 * 60; # 4 hours
-my $accountcode_giveup = 4 * 24 * 60 * 60; # 4 days
+my %sessionnum_unmatch = ();
+my $sessionnum_retry = 4 * 60 * 60; # 4 hours
+my $sessionnum_giveup = 4 * 24 * 60 * 60; # 4 days
while (1) {
@@ -42,8 +42,8 @@ while (1) {
# instead of just doing this search like normal CDRs
#hmm :/
- my @recent = grep { ($accountcode_unmatch{$_} + $accountcode_retry) > time }
- keys %accountcode_unmatch;
+ my @recent = grep { ($sessionnum_unmatch{$_} + $sessionnum_retry) > time }
+ keys %sessionnum_unmatch;
my $extra_sql = scalar(@recent)
? ' AND acctid NOT IN ('. join(',', @recent). ') '
: '';
@@ -92,45 +92,62 @@ while (1) {
}
- if ( $conf->exists('cdr-taqua-accountcode_rewrite')
- && $cdr->lastapp eq 'acctcode' && $cdr->cdrtypenum == 1
+ if ( $cdr->cdrtypenum == 1
+ and $cdr->lastapp
+ and (
+ $conf->exists('cdr-taqua-accountcode_rewrite') or
+ $conf->exists('cdr-taqua-callerid_rewrite') )
)
{
#find the matching CDR
- my $primary = qsearchs('cdr', {
- 'sessionnum' => $cdr->sessionnum,
- 'src' => $cdr->subscriber,
- #'accountcode' => '',
- });
+ my %search = ( 'sessionnum' => $cdr->sessionnum );
+ if ( $cdr->lastapp eq 'acctcode' ) {
+ $search{'src'} = $cdr->subscriber;
+ } elsif ( $cdr->lastapp eq 'CallerId' ) {
+ $search{'dst'} = $cdr->subscriber;
+ }
+ my $primary = qsearchs('cdr', \%search);
unless ( $primary ) {
my $cantfind = "can't find primary CDR with session ". $cdr->sessionnum.
", src ". $cdr->subscriber;
- if ( $cdr->calldate_unix + $accountcode_giveup < time ) {
+ if ( $cdr->calldate_unix + $sessionnum_giveup < time ) {
warn "ERROR: $cantfind; giving up\n";
- push @status, 'taqua-accountcode-NOTFOUND';
+ push @status, 'taqua-sessionnum-NOTFOUND';
$cdr->status('done'); #so it doesn't try to rate
- delete $accountcode_unmatch{$cdr->acctid}; #so it doesn't suck mem
+ delete $sessionnum_unmatch{$cdr->acctid}; #so it doesn't suck mem
} else {
warn "WARNING: $cantfind; will keep trying\n";
- $accountcode_unmatch{$cdr->acctid} = time;
+ $sessionnum_unmatch{$cdr->acctid} = time;
next;
}
} else {
- $primary->accountcode( $cdr->lastdata );
+ if ( $cdr->lastapp eq 'acctcode' ) {
+ # lastdata contains the dialed account code
+ $primary->accountcode( $cdr->lastdata );
+ push @status, 'taqua-accountcode';
+ } elsif ( $cdr->lastapp eq 'CallerId' ) {
+ # lastdata contains "allowed" or "restricted"
+ # or case variants thereof
+ if ( lc($cdr->lastdata) eq 'restricted' ) {
+ $primary->clid( 'PRIVATE' );
+ }
+ push @status, 'taqua-callerid';
+ } else {
+ warn "unknown Taqua service name: ".$cdr->lastapp."\n";
+ }
#$primary->freesiderewritestatus( 'taqua-accountcode-primary' );
- my $error = $primary->replace;
+ my $error = $primary->replace if $primary->modified;
if ( $error ) {
warn "WARNING: error rewriting primary CDR (will retry): $error\n";
next;
}
$skip{$primary->acctid} = 1;
- push @status, 'taqua-accountcode';
$cdr->status('done'); #so it doesn't try to rate
}
@@ -164,7 +181,10 @@ while (1) {
sub _shouldrun {
$conf->exists('cdr-asterisk_forward_rewrite')
|| $conf->exists('cdr-charged_party_rewrite')
- || $conf->exists('cdr-taqua-accountcode_rewrite');
+ || $conf->exists('cdr-taqua-accountcode_rewrite')
+ || $conf->exists('cdr-taqua-callerid_rewrite')
+ || 0
+ ;
}
sub usage {
diff --git a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
index 61361b8..efbd0cd 100644
--- a/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
+++ b/fs_selfservice/FS-SelfService/cgi/selfservice.cgi
@@ -873,6 +873,7 @@ sub view_cdr_details {
'svcnum' => $cgi->param('svcnum'),
'beginning' => $cgi->param('beginning') || '',
'ending' => $cgi->param('ending') || '',
+ 'inbound' => $cgi->param('inbound') || 0,
);
}
diff --git a/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html b/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html
index b0205ec..0ee8e96 100644
--- a/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html
+++ b/fs_selfservice/FS-SelfService/cgi/view_cdr_details.html
@@ -1,5 +1,6 @@
<%= $url = "$selfurl?session=$session_id;action="; ''; %>
-<%= include('header', 'Call usage for '.
+<%= include('header', ($inbound ? 'Received calls' : 'Dialed calls' ) .
+ ' for '.
Date::Format::time2str('%b %o %Y', $beginning).
' - '.
Date::Format::time2str('%b %o %Y', $ending)
diff --git a/fs_selfservice/FS-SelfService/cgi/view_usage.html b/fs_selfservice/FS-SelfService/cgi/view_usage.html
index fd5426a..f707668 100644
--- a/fs_selfservice/FS-SelfService/cgi/view_usage.html
+++ b/fs_selfservice/FS-SelfService/cgi/view_usage.html
@@ -62,11 +62,22 @@
<%= scalar(@svc_acct) ? '</TABLE><BR><BR>' : '' %>
<%= if ( @svc_phone ) {
+ %any = ();
+ for my $dir (qw(outbound inbound)) {
+ $any{$dir} = grep { $_->{$dir} } @svc_phone;
+ }
$OUT.= '<FONT SIZE="4">Call usage</FONT><BR><BR>
<TABLE BGCOLOR="#cccccc">
<TR>
- <TH ALIGN="left">Number</TH>'; #"Account" ?
- #what else?
+ <TH ALIGN="left">Number</TH>';
+ if ( $any{outbound} ) {
+ $OUT .= '
+ <TH>Dialed</TH>';
+ }
+ if ( $any{inbound} ) {
+ $OUT .= '
+ <TH>Received</TH>';
+ }
$OUT .= '</TR>';
} else {
$OUT .= '';
@@ -76,10 +87,27 @@
<%= foreach my $svc_phone ( @svc_phone ) {
my $link = "${url}view_cdr_details;".
"svcnum=$svc_phone->{'svcnum'};beginning=0;ending=0";
- $OUT .= '<TR><TD>';
- $OUT .= qq!<A HREF="$link">!. $svc_phone->{'label'}. ': '. $svc_phone->{'value'}.'</A>';
- $OUT .= '</TD></TR>';
+ $OUT .= '<TR><TD>'. $svc_phone->{'label'}. ': '. $svc_phone->{'value'};
+ $OUT .= '</TD>';
+ # usage summary w/ links
+ for my $dir (qw(outbound inbound)) {
+ if ( $dir eq 'inbound' ) {
+ $link .= ';inbound=1';
+ }
+ if ( $svc_phone->{$dir} ) {
+ $OUT .= '<TD ALIGN="right">'.qq!<A HREF="$link">! .
+ sprintf('%d calls (%.0f minutes)',
+ $svc_phone->{$dir}->{'count'},
+ $svc_phone->{$dir}->{'duration'} / 60
+ ) .
+ '</A></TD>';
+ } elsif ( $any{$dir} ) {
+ $OUT .= '<TD></TD>';
+ }
}
+ $OUT .= '</TR>';
+}
+'';
%>
<%= scalar(@svc_phone) ? '</TABLE><BR><BR>' : '' %>
-----------------------------------------------------------------------
Summary of changes:
FS/FS/ClientAPI/MyAccount.pm | 51 +++++++++++++---
FS/FS/Conf.pm | 35 +++++++++++
FS/FS/cdr.pm | 14 +++--
FS/FS/cdr/taqua62.pm | 4 +-
FS/FS/part_pkg/voip_cdr.pm | 26 ++++++++-
FS/FS/svc_phone.pm | 41 ++++++++++++--
FS/bin/freeside-cdrrewrited | 60 +++++++++++++-------
fs_selfservice/FS-SelfService/cgi/selfservice.cgi | 1 +
.../FS-SelfService/cgi/view_cdr_details.html | 3 +-
fs_selfservice/FS-SelfService/cgi/view_usage.html | 38 +++++++++++--
10 files changed, 222 insertions(+), 51 deletions(-)
More information about the freeside-commits
mailing list