X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fpart_pkg%2Fvoip_cdr.pm;h=d91c4f050274500a7f7bc8fbbc05c4eee2d02587;hb=HEAD;hp=420026dcb51abc89e06158969fe748589d41a36b;hpb=29ed5abdfcc723bf8a3c29a0ae71775a07477033;p=freeside.git diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 420026dcb..d91c4f050 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -4,6 +4,7 @@ use base qw( FS::part_pkg::recur_Common ); use strict; use vars qw( $DEBUG %info ); use Tie::IxHash; +use Date::Parse; use Date::Format; use Text::CSV_XS; use FS::Conf; @@ -25,8 +26,8 @@ tie my %cdr_svc_method, 'Tie::IxHash', tie my %rating_method, 'Tie::IxHash', 'prefix' => 'Rate calls by using destination prefix to look up a region and rate according to the internal prefix and rate tables', # 'upstream' => 'Rate calls based on upstream data: If the call type is "1", map the upstream rate ID directly to an internal rate (rate_detail), otherwise, pass the upstream price through directly.', - 'upstream_simple' => 'Simply pass through and charge the "upstream_price" amount.', - 'single_price' => 'A single price per minute for all calls.', + 'upstream_simple' => 'Simply pass through and charge the "upstream_price" amount (ignoring all options to skip calls).', + 'single_price' => 'A single price per minute for all calls (ignoring all options to skip calls).', ; tie my %rounding, 'Tie::IxHash', @@ -65,7 +66,7 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', ; %info = ( - 'name' => 'VoIP rating by plan of CDR records in an internal (or external) SQL table', + 'name' => 'VoIP rating by plan of CDR records', 'shortname' => 'VoIP/telco CDR rating (standard)', 'inherit_fields' => [ 'prorate_Mixin', 'global_Mixin' ], 'fields' => { @@ -165,9 +166,13 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', }, 'use_cdrtypenum' => { 'name' => 'Only charge for CDRs where the CDR Type is set to this cdrtypenum: ', + 'validate' => \&FS::part_pkg::validate_number_blank, + 'js_validate' => 'digits: true', }, 'ignore_cdrtypenum' => { 'name' => 'Do not charge for CDRs where the CDR Type is set to this cdrtypenum: ', + 'validate' => \&FS::part_pkg::validate_number_blank, + 'js_validate' => 'digits: true', }, 'use_calltypenum' => { 'name' => 'Only charge for CDRs where the CDR Call Type is set to this calltypenum: ', @@ -182,12 +187,22 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', 'disposition_in' => { 'name' => 'Only charge for CDRs where the Disposition is set to any of these (comma-separated) values: ', }, - 'skip_dst_prefix' => { 'name' => 'Do not charge for CDRs where the destination number starts with any of these values: ', + 'disposition_prefix' => { 'name' => 'Only charge for CDRs where the Disposition starts with: ', + }, + + 'skip_dst_prefix' => { 'name' => 'Do not charge for CDRs where the destination number starts with any of these (comma-separated) values: ', }, 'skip_dcontext' => { 'name' => 'Do not charge for CDRs where dcontext is set to any of these (comma-separated) values: ', }, + 'noskip_dcontext_tollfree' => { 'name' => 'Do charge for CDRs where dcontext is set to any of the specified values, if the CDR is tollfree', + 'type' => 'checkbox', + }, + + 'skip_dcontext_prefix' => { 'name' => 'Do not charge for CDRs where dcontext starts with: ', + }, + 'skip_dcontext_suffix' => { 'name' => 'Do not charge for CDRs where dcontext ends with: ', }, @@ -220,6 +235,10 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', 'skip_dst_length_less' => { 'name' => 'Do not charge for CDRs where the destination is less than this many digits:', }, + 'noskip_dst_length_n11' => { 'name' => 'Do charge for CDRs where dst is less than the specified digits, when dst is N11 (i.e. 411, 611)', + 'type' => 'checkbox', + }, + 'noskip_dst_length_accountcode_tollfree' => { 'name' => 'Do charge for CDRs where dst is less than the specified digits, when accountcode is toll free', 'type' => 'checkbox', }, @@ -288,10 +307,9 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', 'bill_only_pkg_dates' => { 'name' => 'Only bill CDRs with a date during the package billing period', 'type' => 'checkbox', }, - - 'count_available_phones' => { 'name' => 'Consider for tax purposes the number of lines to be svc_phones that may be provisioned rather than those that actually are.', - 'type' => 'checkbox', - }, + 'skip_old' => { 'name' => 'Do not charge for CDRs older than: ', + 'type' => 'date', + }, #XXX also have option for an external db? these days we suck them into ours # 'cdr_location' => { 'name' => 'CDR database location' @@ -336,12 +354,14 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', use_carrierid use_cdrtypenum ignore_cdrtypenum use_calltypenum ignore_calltypenum - ignore_disposition disposition_in - skip_dcontext skip_dcontext_suffix skip_dst_prefix + ignore_disposition disposition_in disposition_prefix + skip_dcontext noskip_dcontext_tollfree + skip_dcontext_prefix skip_dcontext_suffix + skip_dst_prefix skip_dstchannel_prefix skip_src_length_more noskip_src_length_accountcode_tollfree accountcode_tollfree_ratenum accountcode_tollfree_field - skip_dst_length_less + skip_dst_length_less noskip_dst_length_n11 noskip_dst_length_accountcode_tollfree skip_lastapp skip_max_callers @@ -352,11 +372,18 @@ tie my %accountcode_tollfree_field, 'Tie::IxHash', selfservice_format selfservice_inbound_format usage_mandate usage_section summarize_usage usage_showzero bill_every_call bill_inactive_svcs - bill_only_pkg_dates - count_available_phones suspend_bill + bill_only_pkg_dates skip_old + suspend_bill ) ], 'weight' => 41, + 'validate' => sub { + # Validation function for FS::part_pkg::check_options() + my $options = shift; + return "Please choose a Rate Plan for use with selected Rating Method" + if $options->{rating_method} eq 'prefix' && !$options->{ratenum}; + return; + }, ); sub price_info { @@ -429,8 +456,6 @@ sub calc_usage { rounding => ($self->option_cacheable('rounding') || 2), ); - my $use_duration = $self->option('use_duration'); - my($svc_table, $svc_field, $by_ip_addr) = split('\.', $cdr_svc_method); my @cust_svc; @@ -566,7 +591,13 @@ sub check_chargable { return "disposition NOT IN ( ". $self->option_cacheable('disposition_in')." )" if $self->option_cacheable('disposition_in') =~ /\S/ && !grep { $cdr->disposition eq $_ } split(/\s*,\s*/, $self->option_cacheable('disposition_in')); - + + my $disposition_prefix = $self->option_cacheable('disposition_prefix'); + my $len_dis_prefix = length($disposition_prefix); + return "disposition does not start with $disposition_prefix" + if $len_dis_prefix + && substr($cdr->disposition, 0, $len_dis_prefix) ne $disposition_prefix; + return "disposition IN ( ". $self->option_cacheable('ignore_disposition')." )" if $self->option_cacheable('ignore_disposition') =~ /\S/ && grep { $cdr->disposition eq $_ } split(/\s*,\s*/, $self->option_cacheable('ignore_disposition')); @@ -601,7 +632,16 @@ sub check_chargable { return "dcontext IN ( ". $self->option_cacheable('skip_dcontext'). " )" if $self->option_cacheable('skip_dcontext') =~ /\S/ - && grep { $cdr->dcontext eq $_ } split(/\s*,\s*/, $self->option_cacheable('skip_dcontext')); + && grep { $cdr->dcontext eq $_ } split(/\s*,\s*/, $self->option_cacheable('skip_dcontext')) + && ! ( $self->option_cacheable('noskip_dcontext_tollfree') + && $cdr->is_tollfree + ); + + my $len_dcontext_prefix = + length($self->option_cacheable('skip_dcontext_prefix')); + return "dcontext starts with ". $self->option_cacheable('skip_dcontext_prefix') + if $len_dcontext_prefix + && substr($cdr->dcontext,0,$len_dcontext_prefix) eq $self->option_cacheable('skip_dcontext_prefix'); my $len_suffix = length($self->option_cacheable('skip_dcontext_suffix')); return "dcontext ends with ". $self->option_cacheable('skip_dcontext_suffix') @@ -616,8 +656,11 @@ sub check_chargable { my $dst_length = $self->option_cacheable('skip_dst_length_less'); return "destination less than $dst_length digits" if $dst_length && length($cdr->dst) < $dst_length - && ! ( $self->option_cacheable('noskip_dst_length_accountcode_tollfree') - && $cdr->is_tollfree('accountcode') + && ! ( $self->option_cacheable('noskip_dst_length_n11') + && $cdr->dst =~ /^\d11$/ + ) + && ! ( $self->option_cacheable('noskip_dst_length_accountcode_tollfree') + && $cdr->is_tollfree('accountcode') ); return "lastapp is ". $self->option_cacheable('skip_lastapp') @@ -648,6 +691,10 @@ sub check_chargable { and length($cdr->max_callers) and $cdr->max_callers <= $self->option_cacheable('skip_max_callers'); + return "calldate < ". $self->option_cacheable('skip_old') + if length($self->option_cacheable('skip_old')) + && $cdr->calldate_unix < str2time($self->option_cacheable('skip_old')); + #all right then, rate it ''; } @@ -656,25 +703,6 @@ sub is_free { 0; } -# This equates svc_phone records; perhaps svc_phone should have a field -# to indicate it represents a line -sub calc_units { - my($self, $cust_pkg ) = @_; - my $count = 0; - if ( $self->option('count_available_phones', 1)) { - foreach my $pkg_svc ($cust_pkg->part_pkg->pkg_svc) { - if ($pkg_svc->part_svc->svcdb eq 'svc_phone') { # svc_pbx? - $count += $pkg_svc->quantity || 0; - } - } - $count *= $cust_pkg->quantity; - } else { - $count = - scalar(grep { $_->part_svc->svcdb eq 'svc_phone' } $cust_pkg->cust_svc); - } - $count; -} - sub reset_usage { my ($self, $cust_pkg, %opt) = @_; my @part_pkg_usage = $self->part_pkg_usage or return ''; @@ -728,4 +756,3 @@ sub hide_svc_detail { 1; -