diff options
| -rw-r--r-- | FS/FS/Conf.pm | 16 | ||||
| -rw-r--r-- | FS/FS/cdr.pm | 15 | ||||
| -rw-r--r-- | FS/FS/part_pkg/voip_cdr.pm | 49 | ||||
| -rw-r--r-- | FS/FS/svc_pbx.pm | 69 | 
4 files changed, 143 insertions, 6 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 99c4876b2..11658a8c1 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -3494,6 +3494,22 @@ and customer address. Include units.',    },    { +    'key'         => 'cdr-charged_party-field', +    'section'     => '', +    'description' => 'Set the charged_party field of CDRs to this field.', +    'type'        => 'select-sub', +    'options_sub' => sub { my $fields = FS::cdr->table_info->{'fields'}; +                           map { $_ => $fields->{$_}||$_ } +                           grep { $_ !~ /^(acctid|charged_party)$/ } +                           FS::Schema::dbdef->table('cdr')->columns; +                         }, +    'option_sub'  => sub { my $f = shift; +                           FS::cdr->table_info->{'fields'}{$f} || $f; +                         }, +  }, + +  #probably deprecate in favor of cdr-charged_party-field above +  {      'key'         => 'cdr-charged_party-accountcode',      'section'     => '',      'description' => 'Set the charged_party field of CDRs to the accountcode.', diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm index 4de7aa35b..34243fae9 100644 --- a/FS/FS/cdr.pm +++ b/FS/FS/cdr.pm @@ -324,15 +324,19 @@ sub check {    $self->SUPER::check;  } -=item is_tollfree +=item is_tollfree [ COLUMN ] -  Returns true when the cdr represents a toll free number and false otherwise. +Returns true when the cdr represents a toll free number and false otherwise. + +By default, inspects the dst field, but an optional column name can be passed +to inspect other field.  =cut  sub is_tollfree {    my $self = shift; -  ( $self->dst =~ /^(\+?1)?8(8|([02-7])\3)/ ) ? 1 : 0; +  my $field = scalar(@_) ? shift : 'dst'; +  ( $self->$field() =~ /^(\+?1)?8(8|([02-7])\3)/ ) ? 1 : 0;  }  =item set_charged_party @@ -361,6 +365,11 @@ sub set_charged_party {          if $conf->exists('cdr-charged_party-accountcode-trim_leading_0s');        $self->charged_party( $charged_party ); +    } elsif ( $conf->exists('cdr-charged_party-field') ) { + +      my $field = $conf->config('cdr-charged_party-field'); +      $self->charged_party( $self->$field() ); +      } else {        if ( $self->is_tollfree ) { diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 77b9af553..02ece07c2 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -17,6 +17,11 @@ use FS::part_pkg::recur_Common;  $DEBUG = 0; +tie my %cdr_svc_method, 'Tie::IxHash', +  'svc_phone.phonenum' => 'Phone numbers (svc_phone.phonenum)', +  'svc_pbx.title'      => 'PBX name (svc_pbx.title)', +; +  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.', @@ -71,6 +76,11 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();                           'select_options' => \%FS::part_pkg::recur_Common::recur_method,                         }, +    'cdr_svc_method' => { 'name' => 'CDR service matching method', +                          'type' => 'radio', +                          'options' => \%cdr_svc_method, +                        }, +      'rating_method' => { 'name' => 'Rating method',                           'type' => 'radio',                           'options' => \%rating_method, @@ -143,6 +153,13 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();      'skip_dstchannel_prefix' => { 'name' => 'Do not charge for CDRs where the dstchannel starts with:',                                  }, +    'skip_src_length_more' => { 'name' => 'Do not charge for CDRs where the source is more than this many digits:', +                              }, + +    'noskip_src_length_accountcode_tollfree' => { 'name' => 'Do charge for CDRs where source is equal or greater than the specified digits and accountcode is toll free', +                                                  'type' => 'checkbox', +                                                }, +      'skip_dst_length_less' => { 'name' => 'Do not charge for CDRs where the destination is less than this many digits:',                                }, @@ -210,6 +227,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();    'fieldorder' => [qw(                         setup_fee recur_fee recur_temporality unused_credit                         recur_method cutoff_day +                       cdr_svc_method                         rating_method ratenum min_charge sec_granularity                         ignore_unrateable                         default_prefix @@ -219,6 +237,7 @@ tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();                         use_amaflags use_disposition                         use_disposition_taqua use_carrierid use_cdrtypenum                         skip_dcontext skip_dstchannel_prefix +                       skip_src_length_more noskip_src_length_accountcode_tollfree                         skip_dst_length_less skip_lastapp                         use_duration                         411_rewrite @@ -278,6 +297,7 @@ sub calc_usage {  #  my $downstream_cdr = ''; +  my $cdr_svc_method    = $self->option('cdr_svc_method')||'svc_phone.phonenum';    my $rating_method     = $self->option('rating_method') || 'prefix';    my $intl              = $self->option('international_prefix') || '011';    my $domestic_prefix   = $self->option('domestic_prefix'); @@ -305,13 +325,15 @@ sub calc_usage {    die $@ if $@;    my $csv = new Text::CSV_XS; +  my($svc_table, $svc_field) = split('.', $cdr_svc_method); +    foreach my $cust_svc ( -    grep { $_->part_svc->svcdb eq 'svc_phone' } $cust_pkg->cust_svc +    grep { $_->part_svc->svcdb eq $svc_table } $cust_pkg->cust_svc    ) { -    my $svc_phone = $cust_svc->svc_x; +    my $svc_x = $cust_svc->svc_x;      foreach my $cdr ( -      $svc_phone->get_cdrs( +      $svc_x->get_cdrs(          'disable_src'    => $self->option('disable_src'),          'default_prefix' => $self->option('default_prefix'),          'status'         => '', @@ -690,6 +712,7 @@ sub check_chargable {      use_cdrtypenum      skip_dcontext      skip_dstchannel_prefix +    skip_src_length_more noskip_src_length_accountcode_tollfree      skip_dst_length_less      skip_lastapp    ); @@ -732,6 +755,26 @@ sub check_chargable {    return "lastapp is $opt{'skip_lastapp'}"      if length($opt{'skip_lastapp'}) && $cdr->lastapp eq $opt{'skip_lastapp'}; +  my $src_length = $opt{'skip_src_length_more'}; +  if ( $src_length ) { + +    if ( $opt{'noskip_src_length_accountcode_tollfree'} ) { + +      if ( $cdr->is_tollfree('accountcode') ) { +        return "source less than or equal to $src_length digits" +          if length($cdr->src) <= $src_length; +      } else { +        return "source more than $src_length digits" +          if length($cdr->src) > $src_length; +      } + +    } else { +      return "source more than $src_length digits" +        if length($cdr->src) > $src_length; +    } + +  } +    #all right then, rate it    '';  } diff --git a/FS/FS/svc_pbx.pm b/FS/FS/svc_pbx.pm index 21aaa4e0b..7c4385cde 100644 --- a/FS/FS/svc_pbx.pm +++ b/FS/FS/svc_pbx.pm @@ -267,6 +267,75 @@ sub _check_duplicate {    }  } +=item get_cdrs + +Returns a set of Call Detail Records (see L<FS::cdr>) associated with this  +service.  By default, "associated with" means that the "charged_party" field of +the CDR matches the "title" field of the service. + +=over 2 + +Accepts the following options: + +=item for_update => 1: SELECT the CDRs "FOR UPDATE". + +=item status => "" (or "done"): Return only CDRs with that processing status. + +=item inbound => 1: No-op for svc_pbx CDR processing. + +=item default_prefix => "XXX": Also accept the phone number of the service prepended  +with the chosen prefix. + +=item disable_src => 1: No-op for svc_pbx CDR processing. + +=back + +=cut + +sub get_cdrs { +  my($self, %options) = @_; +  my %hash = (); +  my @where = (); + +  my @fields = ( 'charged_party' ); +  $hash{'freesidestatus'} = $options{'status'} +    if exists($options{'status'}); +   +  my $for_update = $options{'for_update'} ? 'FOR UPDATE' : ''; + +  my $title = $self->title; + +  my $prefix = $options{'default_prefix'}; + +  my @orwhere =  map " $_ = '$title'        ", @fields; +  push @orwhere, map " $_ = '$prefix$title' ", @fields +    if length($prefix); +  if ( $prefix =~ /^\+(\d+)$/ ) { +    push @orwhere, map " $_ = '$1$title' ", @fields +  } + +  push @where, ' ( '. join(' OR ', @orwhere ). ' ) '; + +  if ( $options{'begin'} ) { +    push @where, 'startdate >= '. $options{'begin'}; +  } +  if ( $options{'end'} ) { +    push @where, 'startdate < '.  $options{'end'}; +  } + +  my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where ); + +  my @cdrs = +    qsearch( { +      'table'      => 'cdr', +      'hashref'    => \%hash, +      'extra_sql'  => $extra_sql, +      'order_by'   => "ORDER BY startdate $for_update", +    } ); + +  @cdrs; +} +  =back  =head1 BUGS  | 
