diff options
| -rw-r--r-- | FS/FS/part_pkg/voip_cdr.pm | 235 | 
1 files changed, 134 insertions, 101 deletions
| diff --git a/FS/FS/part_pkg/voip_cdr.pm b/FS/FS/part_pkg/voip_cdr.pm index 155d8e78c..f7db685a0 100644 --- a/FS/FS/part_pkg/voip_cdr.pm +++ b/FS/FS/part_pkg/voip_cdr.pm @@ -71,6 +71,14 @@ tie my %rating_method, 'Tie::IxHash',                                  'default' => '011',                                }, +    'use_amaflags' => { 'name' => 'Do not charge for CDRs where the amaflags field is not set to "2" ("BILL"/"BILLING").', +                        'type' => 'checkbox', +                      }, + +    'use_disposition' => { 'name' => 'Do not charge for CDRs where the disposition flag is not set to "ANSWERED".', +                           'type' => 'checkbox', +                         }, +      #XXX also have option for an external db  #    'cdr_location' => { 'name' => 'CDR database location'  #                        'type' => 'select', @@ -95,7 +103,15 @@ tie my %rating_method, 'Tie::IxHash',  #                  },    }, -  'fieldorder' => [qw( setup_fee recur_fee unused_credit ratenum rating_method default_prefix disable_src domestic_prefix international_prefix )], +  'fieldorder' => [qw( +                       setup_fee recur_fee unused_credit +                       rating_method ratenum  +                       default_prefix +                       disable_src +                       domestic_prefix international_prefix +                       use_amaflags use_disposition +                     ) +                  ],    'weight' => 40,  ); @@ -135,94 +151,109 @@ sub calc_recur {        my $rate_detail;        my( $rate_region, $regionnum );        my $pretty_destnum; -      my $charge = 0; +      my $charge = '';        my @call_details = ();        if ( $self->option('rating_method') eq 'prefix'             || ! $self->option('rating_method')           )        { -        ### -        # look up rate details based on called station id -        # (or calling station id for toll free calls) -        ### - -        my( $to_or_from, $number ); -        if ( $cdr->dst =~ /^(\+?1)?8([02-8])\1/ ) { #tollfree call -          $to_or_from = 'from'; -          $number = $cdr->src; -        } else { #regular call -          $to_or_from = 'to'; -          $number = $cdr->dst; -        } -   -        #remove non-phone# stuff and whitespace -        $number =~ s/\s//g; -#        my $proto = ''; -#        $dest =~ s/^(\w+):// and $proto = $1; #sip: -#        my $siphost = ''; -#        $dest =~ s/\@(.*)$// and $siphost = $1; # @10.54.32.1, @sip.example.com - -        my $intl = $self->option('international_prefix') || '011'; -   -        #determine the country code -        my $countrycode; -        if (    $number =~ /^$intl(((\d)(\d))(\d))(\d+)$/ -             || $number =~ /^\+(((\d)(\d))(\d))(\d+)$/ -           ) -        { -   -          my( $three, $two, $one, $u1, $u2, $rest ) = ( $1,$2,$3,$4,$5,$6 ); -          #first look for 1 digit country code -          if ( qsearch('rate_prefix', { 'countrycode' => $one } ) ) { -            $countrycode = $one; -            $number = $u1.$u2.$rest; -          } elsif ( qsearch('rate_prefix', { 'countrycode' => $two } ) ) { #or 2 -            $countrycode = $two; -            $number = $u2.$rest; -          } else { #3 digit country code -            $countrycode = $three; -            $number = $rest; -          } -   +        if ( $self->option('use_amaflags') && $cdr->amaflags != 2 ) { + +          warn "not charging for CDR (amaflags != 2)\n" if $DEBUG; +          $charge = 0; + +        } elsif ( $self->option('use_disposition') +                  && $cdr->disposition ne 'ANSWERED' ) { + +          warn "not charging for CDR (disposition != ANSWERED)\n" if $DEBUG; +          $charge = 0; +          } else { -          $countrycode = $self->option('domestic_prefix') || '1'; -          $number =~ s/^$countrycode//;# if length($number) > 10; -        } -   -        warn "rating call $to_or_from +$countrycode $number\n" if $DEBUG; -        $pretty_destnum = "+$countrycode $number"; -   -        #find a rate prefix, first look at most specific (4 digits) then 3, etc., -        # finally trying the country code only -        my $rate_prefix = ''; -        for my $len ( reverse(1..6) ) { -          $rate_prefix = qsearchs('rate_prefix', { + +          ### +          # look up rate details based on called station id +          # (or calling station id for toll free calls) +          ### + +          my( $to_or_from, $number ); +          if ( $cdr->dst =~ /^(\+?1)?8([02-8])\1/ ) { #tollfree call +            $to_or_from = 'from'; +            $number = $cdr->src; +          } else { #regular call +            $to_or_from = 'to'; +            $number = $cdr->dst; +          } + +          #remove non-phone# stuff and whitespace +          $number =~ s/\s//g; +#          my $proto = ''; +#          $dest =~ s/^(\w+):// and $proto = $1; #sip: +#          my $siphost = ''; +#          $dest =~ s/\@(.*)$// and $siphost = $1; # @10.54.32.1, @sip.example.com + +          my $intl = $self->option('international_prefix') || '011'; + +          #determine the country code +          my $countrycode; +          if (    $number =~ /^$intl(((\d)(\d))(\d))(\d+)$/ +               || $number =~ /^\+(((\d)(\d))(\d))(\d+)$/ +             ) +          { + +            my( $three, $two, $one, $u1, $u2, $rest ) = ( $1,$2,$3,$4,$5,$6 ); +            #first look for 1 digit country code +            if ( qsearch('rate_prefix', { 'countrycode' => $one } ) ) { +              $countrycode = $one; +              $number = $u1.$u2.$rest; +            } elsif ( qsearch('rate_prefix', { 'countrycode' => $two } ) ) { #or 2 +              $countrycode = $two; +              $number = $u2.$rest; +            } else { #3 digit country code +              $countrycode = $three; +              $number = $rest; +            } + +          } else { +            $countrycode = $self->option('domestic_prefix') || '1'; +            $number =~ s/^$countrycode//;# if length($number) > 10; +          } + +          warn "rating call $to_or_from +$countrycode $number\n" if $DEBUG; +          $pretty_destnum = "+$countrycode $number"; + +          #find a rate prefix, first look at most specific (4 digits) then 3, etc., +          # finally trying the country code only +          my $rate_prefix = ''; +          for my $len ( reverse(1..6) ) { +            $rate_prefix = qsearchs('rate_prefix', { +              'countrycode' => $countrycode, +              #'npa'         => { op=> 'LIKE', value=> substr($number, 0, $len) } +              'npa'         => substr($number, 0, $len), +            } ) and last; +          } +          $rate_prefix ||= qsearchs('rate_prefix', {              'countrycode' => $countrycode, -            #'npa'         => { op=> 'LIKE', value=> substr($number, 0, $len) } -            'npa'         => substr($number, 0, $len), -          } ) and last; +            'npa'         => '', +          }); + +          # +          die "Can't find rate for call $to_or_from +$countrycode $number\n" +            unless $rate_prefix; + +          $regionnum = $rate_prefix->regionnum; +          $rate_detail = qsearchs('rate_detail', { +            'ratenum'        => $ratenum, +            'dest_regionnum' => $regionnum, +          } ); + +          $rate_region = $rate_prefix->rate_region; + +          warn "  found rate for regionnum $regionnum ". +               "and rate detail $rate_detail\n" +            if $DEBUG; +          } -        $rate_prefix ||= qsearchs('rate_prefix', { -          'countrycode' => $countrycode, -          'npa'         => '', -        }); - -        # -        die "Can't find rate for call $to_or_from +$countrycode $number\n" -          unless $rate_prefix; -   -        $regionnum = $rate_prefix->regionnum; -        $rate_detail = qsearchs('rate_detail', { -          'ratenum'        => $ratenum, -          'dest_regionnum' => $regionnum, -        } ); -   -        $rate_region = $rate_prefix->rate_region; - -        warn "  found rate for regionnum $regionnum ". -             "and rate detail $rate_detail\n" -          if $DEBUG;        } elsif ( $self->option('rating_method') eq 'upstream' ) { @@ -242,7 +273,8 @@ sub calc_recur {          } else { #pass upstream price through            $charge = sprintf('%.2f', $cdr->upstream_price); -   +          $charges += $charge; +            @call_details = (              #time2str("%Y %b %d - %r", $cdr->calldate_unix ),              time2str("%c", $cdr->calldate_unix),  #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot @@ -283,18 +315,19 @@ sub calc_recur {        # don't add it to invoice, don't set its status to NULL,        # don't call downstream_csv or something on it...        # but DO emit a warning... -      if ( ! $rate_detail && ! scalar(@call_details) ) { -   +      #if ( ! $rate_detail && ! scalar(@call_details) ) { +      if ( ! $rate_detail && $charge eq '' ) { +          warn "no rate_detail found for CDR.acctid:  ". $cdr->acctid.               "; skipping\n"        } else { # there *is* a rate_detail (or call_details), proceed... -        unless ( @call_details ) { -     +        unless ( @call_details || ( $charge ne '' && $charge == 0 ) ) { +            $included_min{$regionnum} = $rate_detail->min_included              unless exists $included_min{$regionnum}; -       +            my $granularity = $rate_detail->sec_granularity;            my $seconds = $cdr->billsec; # length($cdr->billsec) ? $cdr->billsec : $cdr->duration;            $seconds += $granularity - ( $seconds % $granularity ) @@ -305,19 +338,19 @@ sub calc_recur {            # per call rather than per minute            $minutes = 1 unless $granularity; -       +            $included_min{$regionnum} -= $minutes; -       +            if ( $included_min{$regionnum} < 0 ) {              my $charge_min = 0 - $included_min{$regionnum};              $included_min{$regionnum} = 0;              $charge = sprintf('%.2f', $rate_detail->min_charge * $charge_min );              $charges += $charge;            } -       +            # this is why we need regionnum/rate_region....            warn "  (rate region $rate_region)\n" if $DEBUG; -       +            @call_details = (              #time2str("%Y %b %d - %r", $cdr->calldate_unix ),              time2str("%c", $cdr->calldate_unix),  #XXX this should probably be a config option dropdown so they can select US vs- rest of world dates or whatnot @@ -328,25 +361,25 @@ sub calc_recur {            );          } -     -        warn "  adding details on charge to invoice: ". -             join(' - ', @call_details ) -          if $DEBUG && $charge > 0; -     -        push @$details, join(' - ', @call_details) #\@call_details, -          if $charge > 0; -   + +        if ( $charge > 0 ) { +          my $call_details = join(' - ', @call_details ); +          warn "  adding details on charge to invoice: $call_details" +            if $DEBUG; +          push @$details, $call_details; #\@call_details, +        } +          # if the customer flag is on, call "downstream_csv" or something          # like it to export the call downstream!          # XXX price plan option to pick format, or something...          $downstream_cdr .= $cdr->downstream_csv( 'format' => 'convergent' )            if $spool_cdr; -   +          my $error = $cdr->set_status_and_rated_price('done', $charge);          die $error if $error; -   +        } -   +      } # $cdr    } # $cust_svc | 
