From: mark Date: Fri, 11 Feb 2011 23:59:29 +0000 (+0000) Subject: rate selection by CDR type, RT#10991 X-Git-Tag: freeside_2_3_0~627 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=6a10d16ff4e806357abab206254aa38c80a749d3 rate selection by CDR type, RT#10991 --- diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 71403b428..040f6df21 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -2489,6 +2489,7 @@ sub tables_hashref { 'sec_granularity', 'int', '', '', '', '', 'ratetimenum', 'int', 'NULL', '', '', '', 'classnum', 'int', 'NULL', '', '', '', + 'cdrtypenum', 'int', 'NULL', '', '', '', ], 'primary_key' => 'ratedetailnum', 'unique' => [ [ 'ratenum', 'orig_regionnum', 'dest_regionnum' ] ], diff --git a/FS/FS/cdr_type.pm b/FS/FS/cdr_type.pm index e258bf878..d16b85cf6 100644 --- a/FS/FS/cdr_type.pm +++ b/FS/FS/cdr_type.pm @@ -34,7 +34,7 @@ FS::Record. The following fields are currently supported: =item cdrtypenum - primary key -=item typename - CDR type name +=item cdrtypename - CDR type name =back @@ -98,7 +98,7 @@ sub check { my $error = $self->ut_numbern('cdrtypenum') - || $self->ut_text('typename') + || $self->ut_text('cdrtypename') ; return $error if $error; diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index fea38c1d0..800f92924 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -333,7 +333,7 @@ sub calc_usage { my $disable_tollfree = $self->option('disable_tollfree'); my $ignore_unrateable = $self->option('ignore_unrateable', 'Hush!'); my $use_duration = $self->option('use_duration'); - my $region_group = ($rating_method eq 'prefix' && $self->option('min_included') > 0); + my $region_group = ($rating_method eq 'prefix' && ($self->option('min_included') || 0) > 0); my $region_group_included_min = $region_group ? $self->option('min_included') : 0; my $output_format = $self->option('output_format', 'Hush!') @@ -502,6 +502,7 @@ sub calc_usage { $rate_detail = $rate->dest_detail({ 'countrycode' => $countrycode, 'phonenum' => $number, 'weektime' => $weektime, + 'cdrtypenum' => $cdr->cdrtypenum, }); if ( $rate_detail ) { @@ -568,10 +569,7 @@ sub calc_usage { if $seconds # don't granular-ize 0 billsec calls (bills them) && $granularity # 0 is per call && $seconds % $granularity; - my $minutes = $seconds / 60; - # XXX config? - #$charge = sprintf('%.2f', ( $self->option('min_charge') * $minutes ) - #+ 0.00000001 ); #so 1.005 rounds to 1.01 + my $minutes = $granularity ? ($seconds / 60) : 1; $charge = sprintf('%.4f', ( $self->option('min_charge') * $minutes ) + 0.0000000001 ); #so 1.00005 rounds to 1.0001 @@ -692,7 +690,8 @@ sub calc_usage { # choose next rate_detail $rate_detail = $rate->dest_detail({ 'countrycode' => $countrycode, 'phonenum' => $number, - 'weektime' => $etime }) + 'weektime' => $etime, + 'cdrtypenum' => $cdr->cdrtypenum }) if($seconds_left); # we have now moved forward to $etime $weektime = $etime; diff --git a/FS/FS/rate.pm b/FS/FS/rate.pm index f30e4c772..02d8250eb 100644 --- a/FS/FS/rate.pm +++ b/FS/FS/rate.pm @@ -276,25 +276,34 @@ specificed destination, or the empty string if no rate can be found for the given destination. Destination can be specified as an FS::rate_detail object or regionnum -(see L), or as a hashref with two keys: I -and I. +(see L), or as a hashref containing the following keys: -An optional third key, I, will return a timed rate (one with -a non-null I) if one exists for a call at that time. If -no matching timed rate exists, the non-timed rate will be returned. +=over 2 + +=item I - required. + +=item I - required. + +=item I - optional. Specifies a time in seconds from the start +of the week, and will return a timed rate (one with a non-null I) +if one exists at that time. If not, returns a non-timed rate. + +=item I - optional. Specifies a value for the cdrtypenum +field, and will return a rate matching that, if one exists. If not, returns +a rate with null cdrtypenum. =cut sub dest_detail { my $self = shift; - my $regionnum; - my $weektime; + my( $regionnum, $weektime, $cdrtypenum ); if ( ref($_[0]) eq 'HASH' ) { my $countrycode = $_[0]->{'countrycode'}; my $phonenum = $_[0]->{'phonenum'}; $weektime = $_[0]->{'weektime'}; + $cdrtypenum = $_[0]->{'cdrtypenum'} || ''; #find a rate prefix, first look at most specific, then fewer digits, # finally trying the country code only @@ -315,36 +324,47 @@ sub dest_detail { $regionnum = $rate_prefix->regionnum; - #$rate_region = $rate_prefix->rate_region; - } else { $regionnum = ref($_[0]) ? shift->regionnum : shift; } - - if(!defined($weektime)) { - return qsearchs( 'rate_detail', - { 'ratenum' => $self->ratenum, - 'dest_regionnum' => $regionnum, - 'ratetimenum' => '', - } ); + + my %hash = ( + 'ratenum' => $self->ratenum, + 'dest_regionnum' => $regionnum, + ); + + # find all rates matching ratenum, regionnum, cdrtypenum + my @details = qsearch( 'rate_detail', { + %hash, + 'cdrtypenum' => $cdrtypenum + }); + # find all rates maching ratenum, regionnum and null cdrtypenum + if ( !@details and $cdrtypenum ) { + @details = qsearch( 'rate_detail', { + %hash, + 'cdrtypenum' => '' + }); } - else { - my @details = grep { my $rate_time = $_->rate_time; - $rate_time && $rate_time->contains($weektime) } - qsearch( 'rate_detail', - { 'ratenum' => $self->ratenum, - 'dest_regionnum' => $regionnum, } ); - if(!@details) { - # this may change at some point - return $self->dest_detail($regionnum); + # find one of those matching weektime + if ( defined($weektime) ) { + my @exact = grep { + my $rate_time = $_->rate_time; + $rate_time && $rate_time->contains($weektime) + } @details; + if ( @exact == 1 ) { + return $exact[0]; } - elsif(@details == 1) { - return $details[0]; - } - else { - die "overlapping rate_detail times (region $regionnum, time $weektime)\n"; + elsif ( @exact > 1 ) { + die "overlapping rate_detail times (region $regionnum, time $weektime)\n" } + # else @exact == 0 + } + # if not found or there is no weektime, find one matching null weektime + foreach (@details) { + return $_ if $_->ratetimenum eq ''; } + # found nothing + return; } =item rate_detail diff --git a/FS/FS/rate_detail.pm b/FS/FS/rate_detail.pm index 7b9045205..918134a3a 100644 --- a/FS/FS/rate_detail.pm +++ b/FS/FS/rate_detail.pm @@ -57,6 +57,8 @@ inherits from FS::Record. The following fields are currently supported: =item ratetimenum - rating time period (see L) if any for this rate + =back =head1 METHODS @@ -234,6 +236,20 @@ sub classname { $usage_class ? $usage_class->classname : ''; } +=item cdrtypename + +Returns the name of the CDR type (see Lcdrtypenum or return ''; + my $cdr_type = qsearchs('cdr_type', { cdrtypenum => $cdrtypenum }); + return $cdr_type ? $cdr_type->cdrtypename : $cdrtypenum; +} =back diff --git a/httemplate/browse/elements/browse.html b/httemplate/browse/elements/browse.html index 513c2c4e9..9099d6538 100644 --- a/httemplate/browse/elements/browse.html +++ b/httemplate/browse/elements/browse.html @@ -1,5 +1,5 @@ <% include( '/search/elements/search.html', - 'disable_download' => 1, + 'really_disable_download' => 1, 'disable_nonefound' => 1, @_, ) diff --git a/httemplate/browse/rate.cgi b/httemplate/browse/rate.cgi index c6cfec074..0c425a5d1 100644 --- a/httemplate/browse/rate.cgi +++ b/httemplate/browse/rate.cgi @@ -4,6 +4,8 @@ $p.'browse/rate_region.html', 'Time Periods' => $p.'browse/rate_time.html', + 'CDR Types' => + $p.'edit/cdr_type.cgi', ], 'html_init' => $html_init, 'name' => 'rate plans', @@ -15,6 +17,7 @@ 'header' => [ '#', 'Rate plan', 'Rates' ], 'fields' => [ 'ratenum', 'ratename', $rates_sub ], 'links' => [ $link, $link, '' ], + 'really_disable_download' => 1 ) %> <%once> @@ -27,7 +30,7 @@ my $rates_sub = sub { my $rate = shift; my $ratenum = $rate->ratenum; - qq(
+ qq(

+<% include('/elements/footer.html') %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my @data = ( + map { [ $_->cdrtypenum, $_->cdrtypename ] } + qsearch({ + 'table' => 'cdr_type', + 'hashref' => {}, + 'order_by' => 'ORDER BY cdrtypenum ASC' + }) +); + + diff --git a/httemplate/edit/process/cdr_type.cgi b/httemplate/edit/process/cdr_type.cgi new file mode 100644 index 000000000..b661de75d --- /dev/null +++ b/httemplate/edit/process/cdr_type.cgi @@ -0,0 +1,42 @@ +% if ( $error ) { +% $cgi->param('error', $error); +<% $cgi->redirect(popurl(2). "cdr_type.cgi?". $cgi->query_string ) %> +% } else { +<% $cgi->redirect(popurl(2). "cdr_type.cgi" ) %> +% } +<%init> +my $error = ''; +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my %vars = $cgi->Vars; +warn Dumper(\%vars)."\n"; + +my %old = map { $_->cdrtypenum => $_ } qsearch('cdr_type', {}); + +my @new; +foreach ( keys(%vars) ) { + my ($i) = /^cdrtypenum(\d+)$/ or next; + my $cdrtypenum = $vars{"cdrtypenum$i"} or next; + my $cdrtypename = $vars{"cdrtypename$i"} or next; + # don't delete unchanged records + if ( $old{$i} and $old{$i}->cdrtypename eq $cdrtypename ) { + delete $old{$i}; + next; + } + push @new, FS::cdr_type->new({ + 'cdrtypenum' => $cdrtypenum, + 'cdrtypename' => $cdrtypename, + }); +} +foreach (values(%old)) { + $error = $_->delete; + last if $error; +} +if(!$error) { + foreach (@new) { + $error = $_->insert; + last if $error; + } +} + diff --git a/httemplate/edit/rate.cgi b/httemplate/edit/rate.cgi index 13717dc1a..1abfb0d32 100644 --- a/httemplate/edit/rate.cgi +++ b/httemplate/edit/rate.cgi @@ -26,8 +26,24 @@ Rate plan % if($rate->ratenum) {

Rates in this plan +% if ( my $select_cdr_type = include('/elements/select-cdr_type.html', +% 'curr_value' => $cdrtypenum, +% 'onchange' => 'form.submit();', +% 'name_col' => 'cdrtypename', +% 'value_col' => 'cdrtypenum', +% 'empty_label' => '(default)', +% ) ) { +
+ + +Usage type: <% $select_cdr_type %> +
+% } + <% include('/edit/elements/rate_detail.html', - 'ratenum' => $rate->ratenum + 'ratenum' => $rate->ratenum, + 'countrycode' => $countrycode, + 'cdrtypenum' => $cdrtypenum, ) %> % } @@ -39,13 +55,21 @@ die "access denied" unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); my $rate; -if ( $cgi->keywords ) { - my($query) = $cgi->keywords; - $query =~ /^(\d+)$/; +if ( $cgi->param('ratenum') ) { + $cgi->param('ratenum') =~ /^(\d+)$/; $rate = qsearchs( 'rate', { 'ratenum' => $1 } ); } else { #adding $rate = new FS::rate {}; } my $action = $rate->ratenum ? 'Edit' : 'Add'; +my $countrycode = ''; +if ( $cgi->param('countrycode') =~ /^(\d+)$/ ) { + $countrycode = $1; +} + +my $cdrtypenum = ''; +if ( $cgi->param('cdrtypenum') =~ /^(\d+)$/ ) { + $cdrtypenum = $1; +} diff --git a/httemplate/edit/rate_detail.html b/httemplate/edit/rate_detail.html index ec04e4cbb..19378209e 100644 --- a/httemplate/edit/rate_detail.html +++ b/httemplate/edit/rate_detail.html @@ -18,6 +18,7 @@ { field=>'orig_regionnum', type=>'hidden', }, { field=>'dest_regionnum', type=>'hidden', }, { field=>'ratetimenum', type=>'hidden', }, + { field=>'cdrtypenum', type=>'hidden', }, { field=>'dest_regionname', type=>'fixed', }, { field=>'dest_prefixes_short', type=>'fixed', }, { field=>'rate_time_name', type=>'fixed', }, @@ -49,6 +50,9 @@ { ratenum => $cgi->param('ratenum'), dest_regionnum => $cgi->param('dest_regionnum'), ratetimenum => $cgi->param('ratetimenum'), + cdrtypenum => $cgi->param('cdrtypenum'), + min_included => 0, + conn_charge => 0, } }, ) diff --git a/httemplate/edit/rate_region.cgi b/httemplate/edit/rate_region.cgi index cae30030a..367bbafb6 100644 --- a/httemplate/edit/rate_region.cgi +++ b/httemplate/edit/rate_region.cgi @@ -35,17 +35,28 @@ -

+
"> %# rate plan info, if the region has been created yet % if($rate_region->regionnum) { -
-
-Rates in this region +

Rates in this region +% if ( my $select_cdr_type = include('/elements/select-cdr_type.html', +% 'curr_value' => $cdrtypenum, +% 'onchange' => 'form.submit();', +% 'name_col' => 'cdrtypename', +% 'value_col' => 'cdrtypenum', +% 'empty_label' => '(default)', +% ) ) { +
+ +Usage type: <% $select_cdr_type %> +
+% } <% include('/edit/elements/rate_detail.html', - 'regionnum' => $rate_region->regionnum, + 'regionnum' => $rate_region->regionnum, + 'cdrtypenum' => $cdrtypenum, ) %> % } @@ -68,9 +79,8 @@ if ( $cgi->param('error') ) { $rate_region = new FS::rate_region ( { map { $_, scalar($cgi->param($_)) } fields('rate_region') } ); -} elsif ( $cgi->keywords ) { - my($query) = $cgi->keywords; - $query =~ /^(\d+)$/ or die "unparsable regionnum"; +} elsif ( $cgi->param('regionnum') ) { + $cgi->param('regionnum') =~ /^(\d+)$/ or die "unparseable regionnum"; $rate_region = qsearchs( 'rate_region', { 'regionnum' => $1 } ) or die "unknown regionnum $1\n"; } else { #adding @@ -91,5 +101,8 @@ if ( @rate_prefix ) { unless $rate_prefix->countrycode eq $countrycode; } } - +my $cdrtypenum = ''; +if ( $cgi->param('cdrtypenum') =~ /^(\d+)$/ ) { + $cdrtypenum = $1; +} diff --git a/httemplate/elements/auto-table.html b/httemplate/elements/auto-table.html index 9c7dfd09a..49222745a 100644 --- a/httemplate/elements/auto-table.html +++ b/httemplate/elements/auto-table.html @@ -51,7 +51,9 @@ Values will be passed through as "mytable_id1", etc. % my $col = 0; % for ( $col = 0; $col < scalar @fields; $col++ ) { -% my $id = $prefix . $fields[$col] . $row; +% my $id = $prefix . $fields[$col]; +% # don't suffix rownum in the final, blank row +% $id .= $row if $row < (scalar @data) - 1; % my @o = @{ $select[$col] }; % if( @o ) { @@ -117,7 +119,10 @@ $val eq $data[$row][$col] ? ' SELECTED' : ''%>><% shift @o %> var row = <% $prefix %>table.insertRow(-1); var cells = <% $prefix %>_blank.cells; for (i=0; irownum++; } diff --git a/httemplate/elements/select-cdr_type.html b/httemplate/elements/select-cdr_type.html new file mode 100644 index 000000000..9d260898a --- /dev/null +++ b/httemplate/elements/select-cdr_type.html @@ -0,0 +1,11 @@ +% if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM cdr_type') ) { +<% include( '/elements/select-table.html', + 'table' => 'cdr_type', + 'name_col' => 'cdrtypenum', + 'empty_label' => '(none)', + @_ + ) +%> +% } +<%init> +