summaryrefslogtreecommitdiff
path: root/FS/FS
diff options
context:
space:
mode:
Diffstat (limited to 'FS/FS')
-rw-r--r--FS/FS/Schema.pm1
-rw-r--r--FS/FS/cdr_type.pm4
-rw-r--r--FS/FS/part_pkg/voip_cdr.pm11
-rw-r--r--FS/FS/rate.pm80
-rw-r--r--FS/FS/rate_detail.pm16
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