diff options
Diffstat (limited to 'FS/FS')
-rw-r--r-- | FS/FS/Schema.pm | 1 | ||||
-rw-r--r-- | FS/FS/cdr_type.pm | 4 | ||||
-rw-r--r-- | FS/FS/part_pkg/voip_cdr.pm | 11 | ||||
-rw-r--r-- | FS/FS/rate.pm | 80 | ||||
-rw-r--r-- | FS/FS/rate_detail.pm | 16 |
5 files changed, 74 insertions, 38 deletions
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 71403b4..040f6df 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 e258bf8..d16b85c 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 fea38c1..800f929 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 f30e4c7..02d8250 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<FS::rate_detail>), or as a hashref with two keys: I<countrycode> -and I<phonenum>. +(see L<FS::rate_detail>), or as a hashref containing the following keys: -An optional third key, I<weektime>, will return a timed rate (one with -a non-null I<ratetimenum>) 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<countrycode> - required. + +=item I<phonenum> - required. + +=item I<weektime> - optional. Specifies a time in seconds from the start +of the week, and will return a timed rate (one with a non-null I<ratetimenum>) +if one exists at that time. If not, returns a non-timed rate. + +=item I<cdrtypenum> - 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 7b90452..918134a 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<FS::rate_time) if any +=item cdrtypenum - CDR type (see L<FS::cdr_type>) 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 L<FS::cdr_type) associated with this +rate, if there is one. If not, returns the cdrtypenum itself. This will +only return an empty string if cdrtypenum is NULL. + +=cut + +sub cdrtypename { + my $self = shift; + my $cdrtypenum = $self->cdrtypenum or return ''; + my $cdr_type = qsearchs('cdr_type', { cdrtypenum => $cdrtypenum }); + return $cdr_type ? $cdr_type->cdrtypename : $cdrtypenum; +} =back |