package FS::part_pkg::voip_inbound;
+use base qw( FS::part_pkg::recur_Common );
use strict;
-use vars qw(@ISA $DEBUG %info);
+use vars qw($DEBUG %info);
use Date::Format;
use Tie::IxHash;
+use Text::CSV_XS;
use FS::Conf;
use FS::Record qw(qsearchs qsearch);
-use FS::part_pkg::recur_Common;
use FS::cdr;
-use FS::part_pkg::recur_Common;
-
-@ISA = qw(FS::part_pkg::recur_Common);
+use FS::rate_detail;
+use FS::detail_format;
$DEBUG = 0;
'default' => '+1',
},
- 'disable_tollfree' => { 'name' => 'Disable automatic toll-free processing',
- 'type' => 'checkbox',
- },
-
- 'use_amaflags' => { 'name' => 'Do not charge for CDRs where the amaflags field is not set to "2" ("BILL"/"BILLING").',
+ 'use_amaflags' => { 'name' => 'Only charge for CDRs where the amaflags field is set to "2" ("BILL"/"BILLING").',
'type' => 'checkbox',
},
- 'use_carrierid' => { 'name' => 'Do not charge for CDRs where the Carrier ID is not set to: ',
+ 'use_carrierid' => { 'name' => 'Only charge for CDRs where the Carrier ID is set to: ',
},
- 'use_cdrtypenum' => { 'name' => 'Do not charge for CDRs where the CDR Type is not set to: ',
+ 'use_cdrtypenum' => { 'name' => 'Only charge for CDRs where the CDR Type is set to: ',
},
'ignore_cdrtypenum' => { 'name' => 'Do not charge for CDRs where the CDR Type is set to: ',
'ignore_disposition' => { 'name' => 'Do not charge for CDRs where the Disposition is set to any of these (comma-separated) values: ',
},
- 'disposition_in' => { 'name' => 'Do not charge for CDRs where the Disposition is not set to any of these (comma-separated) values: ',
+ 'disposition_in' => { 'name' => 'Only charge for CDRs where the Disposition is set to any of these (comma-separated) values: ',
},
'skip_dcontext' => { 'name' => 'Do not charge for CDRs where the dcontext is set to any of these (comma-separated) values:',
FS::part_pkg::prorate_Mixin::fieldorder,
qw( min_charge min_included sec_granularity
default_prefix
- disable_tollfree
use_amaflags
use_carrierid
use_cdrtypenum ignore_cdrtypenum
bill_every_call
)
],
- 'weight' => 40,
+ 'weight' => 42,
);
sub price_info {
}
-sub calc_cancel {
- my $self = shift;
- my($cust_pkg, $sdate, $details, $param ) = @_;
-
- $self->calc_usage(@_);
-}
+# use the default
+#sub calc_cancel {
+# my $self = shift;
+# my($cust_pkg, $sdate, $details, $param ) = @_;
+#
+# $self->calc_usage(@_);
+#}
#false laziness w/voip_sqlradacct calc_recur resolve it if that one ever gets used again
my $spool_cdr = $cust_pkg->cust_main->spool_cdr;
- my $included_min = ($self->option('min_included')
- && $self->option('min_included') > 0)
- ? $self->option('min_included') : 0;
my $charges = 0;
# my $downstream_cdr = '';
- my $disable_tollfree = $self->option('disable_tollfree');
- my $ignore_unrateable = $self->option('ignore_unrateable', 'Hush!');
- my $use_duration = $self->option('use_duration');
+ my $included_min = $self->option('min_included', 1) || 0;
+ my $use_duration = $self->option('use_duration');
+ my $output_format = $self->option('output_format', 1) || 'default';
+
+ my $formatter =
+ FS::detail_format->new($output_format, buffer => $details, inbound => 1);
- my $output_format = $self->option('output_format', 'Hush!') || 'default';
+ my $granularity = length($self->option('sec_granularity'))
+ ? $self->option('sec_granularity')
+ : 60;
#for check_chargable, so we don't keep looking up options inside the loop
my %opt_cache = ();
- eval "use Text::CSV_XS;";
- die $@ if $@;
my $csv = new Text::CSV_XS;
foreach my $cust_svc (
) {
my $svc_phone = $cust_svc->svc_x;
- foreach my $cdr ( $svc_phone->get_cdrs(
- 'for_update' => 1,
- 'status' => '', # unprocessed only
- 'default_prefix' => $self->option('default_prefix'),
+ my $cdr_search = $svc_phone->psearch_cdrs(
'inbound' => 1,
- )
- ) {
+ 'default_prefix' => $self->option('default_prefix'),
+ 'status' => '', # unprocessed only
+ 'for_update' => 1,
+ );
+ $cdr_search->limit(1000);
+ $cdr_search->increment(0);
+ while ( my $cdr = $cdr_search->fetch ) {
+
+ my $reason = $self->check_chargable( $cdr,
+ 'option_cache' => \%opt_cache,
+ );
+ if ( $reason ) {
+ warn "not charging for CDR ($reason)\n" if $DEBUG;
+ $cdr_search->adjust(1);
+ next;
+ }
+
if ( $DEBUG > 1 ) {
warn "rating inbound CDR $cdr\n".
join('', map { " $_ => ". $cdr->{$_}. "\n" } keys %$cdr );
}
- my $granularity = length($self->option('sec_granularity'))
- ? $self->option('sec_granularity')
- : 60;
my $seconds = $use_duration ? $cdr->duration : $cdr->billsec;
$included_min = 0;
}
- $charge = sprintf('%.2f', ( $self->option('min_charge') * $charge_min )
+ $charge = sprintf('%.4f', ( $self->option('min_charge') * $charge_min )
+ 0.00000001 ); #so 1.00005 rounds to 1.0001
if ( $charge > 0 ) {
$charges += $charge;
- my @call_details = ($cdr->downstream_csv( 'format' => $output_format,
- 'charge' => $charge,
- 'minutes' => $minutes,
- 'granularity' => $granularity,
- )
- );
- push @$details,
- [ 'C',
- $call_details[0],
- $charge,
- $cdr->calltypenum, #classnum
- $self->phonenum,
- $cdr->accountcode,
- $cdr->startdate,
- $seconds,
- '', #regionname, not set for inbound calls
- ];
- }
-
- my $error = $cdr->set_status_and_rated_price( 'done',
- $charge,
- $cust_svc->svcnum,
- 'inbound' => 1 );
- die $error if $error;
+ my @call_details = (
+ $cdr->downstream_csv( 'format' => $output_format,
+ 'charge' => $charge,
+ 'seconds' => ($use_duration
+ ? $cdr->duration
+ : $cdr->billsec
+ ),
+ 'granularity' => $granularity,
+ )
+ );
+# push @$details,
+# { format => 'C',
+# detail => $call_details[0],
+# amount => $charge,
+# classnum => $cdr->calltypenum, #classnum
+# #phonenum => $self->phonenum,
+# accountcode => $cdr->accountcode,
+# startdate => $cdr->startdate,
+# duration => $seconds,
+# # regionname?? => '', #regionname, not set for inbound calls
+# };
+ }
+
+ # eventually use FS::cdr::rate for this
+ my $error = $cdr->set_status_and_rated_price(
+ 'done',
+ $charge,
+ $cust_svc->svcnum,
+ 'rated_seconds' => $use_duration ? $cdr->duration : $cdr->billsec,
+ 'rated_granularity' => $granularity,
+ 'rated_classnum' => $cdr->calltypenum,
+ 'inbound' => 1,
+ );
+ die $error if $error;
+ $formatter->append($cdr);
+
+ $cdr_search->adjust(1) if $cdr->freesidestatus eq '';
} #$cdr
} # $cust_svc
- unshift @$details, [ 'C',
- FS::cdr::invoice_header($output_format),
- '',
- '',
- '',
- '',
- '',
- ]
- if @$details;
+# unshift @$details, { format => 'C',
+# detail => FS::cdr::invoice_header($output_format),
+# }
+# if @$details;
+
+ $formatter->finish;
+ unshift @$details, $formatter->header if @$details;
$charges;
}
return "carrierid != $opt{'use_carrierid'}"
if length($opt{'use_carrierid'})
- && $cdr->carrierid ne $opt{'use_carrierid'} #ne otherwise 0 matches ''
- && ! $flags{'da_rewrote'};
+ && $cdr->carrierid ne $opt{'use_carrierid'}; #ne otherwise 0 matches ''
return "cdrtypenum != $opt{'use_cdrtypenum'}"
if length($opt{'use_cdrtypenum'})