'svc_phone.phonenum' => 'Phone numbers (svc_phone.phonenum)',
'svc_pbx.title' => 'PBX name (svc_pbx.title)',
'svc_pbx.svcnum' => 'Freeside service # (svc_pbx.svcnum)',
+ 'svc_pbx.ip.src' => 'PBX name to source IP address',
+ 'svc_pbx.ip.dst' => 'PBX name to destination IP address',
;
tie my %rating_method, 'Tie::IxHash',
},
'cdr_svc_method' => { 'name' => 'CDR service matching method',
- 'type' => 'radio',
- 'options' => \%cdr_svc_method,
+# 'type' => 'radio',
+ 'type' => 'select',
+ 'select_options' => \%cdr_svc_method,
},
'rating_method' => { 'name' => 'Rating method',
'empty_label' => '',
},
- 'min_included' => { 'name' => 'Minutes included when using the "single price per minute" rating method or when using the "prefix" rating method ("region group" billing)',
+ 'calls_included' => { 'name' => 'Number of calls included at no usage charge', },
+
+ 'min_included' => { 'name' => 'Minutes included when using the "single price per minute" or "prefix" rating method',
},
'min_charge' => { 'name' => 'Charge per minute when using "single price per minute" rating method',
},
#eofalse
+ 'usage_nozero' => { 'name' => 'Omit details for included / no-charge calls.',
+ 'type' => 'checkbox',
+ },
+
'bill_every_call' => { 'name' => 'Generate an invoice immediately for every call (as well any setup fee, upon first payment). Useful for prepaid.',
'type' => 'checkbox',
},
qw(
cdr_svc_method
rating_method ratenum intrastate_ratenum
+ calls_included
min_charge min_included sec_granularity
ignore_unrateable
default_prefix
}
-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 $charges = 0;
my $included_min = $self->option('min_included', 1) || 0; #single price rating
+ my $included_calls = $self->option('calls_included', 1) || 0;
my $cdr_svc_method = $self->option('cdr_svc_method',1)||'svc_phone.phonenum';
my $rating_method = $self->option('rating_method') || 'prefix';
: 'default'
);
+ my $usage_nozero = $self->option->('usage_nozero', 1);
+
my $formatter = FS::detail_format->new($output_format, buffer => $details);
my $use_duration = $self->option('use_duration');
- my($svc_table, $svc_field) = split('\.', $cdr_svc_method);
+ my($svc_table, $svc_field, $by_ip_addr) = split('\.', $cdr_svc_method);
my @cust_svc;
if( $self->option('bill_inactive_svcs',1) ) {
'status' => '',
'for_update' => 1,
); # $last_bill, $$sdate )
- $options{'by_svcnum'} = 1 if $svc_field eq 'svcnum';
+ if ( $svc_field eq 'svcnum' ) {
+ $options{'by_svcnum'} = 1;
+ }
+ elsif ($svc_table eq 'svc_pbx' and $svc_field eq 'ip') {
+ $options{'by_ip_addr'} = $by_ip_addr;
+ }
#my @invoice_details_sort;
#first rate any outstanding CDRs not yet rated
- foreach my $cdr (
- $svc_x->get_cdrs( %options )
- ) {
+ my $cdr_search = $svc_x->psearch_cdrs(%options);
+ $cdr_search->limit(1000);
+ $cdr_search->increment(0); # because we're changing their status as we go
+ while ( my $cdr = $cdr_search->fetch ) {
my $error = $cdr->rate(
'part_pkg' => $self,
);
die $error if $error; #??
+ $cdr_search->adjust(1) if $cdr->freesidestatus eq '';
+ # it was skipped without changing status, so increment the
+ # offset so that we don't re-fetch it on refill
+
} # $cdr
#then add details to invoices & get a total
$options{'status'} = 'rated';
- foreach my $cdr (
- $svc_x->get_cdrs( %options )
- ) {
+ $cdr_search = $svc_x->psearch_cdrs(%options);
+ $cdr_search->limit(1000);
+ $cdr_search->increment(0);
+ while ( my $cdr = $cdr_search->fetch ) {
+ my $error;
# at this point we officially Do Not Care about the rating method
- $charges += $cdr->rated_price;
- $formatter->append($cdr);
- }
+ if ( $included_calls > 0 ) {
+ $included_calls--;
+ #$charges += 0, obviously
+ #but don't set the rated price to zero--there should be a record
+ $error = $cdr->set_status('no-charge');
+ }
+ else {
+ $charges += $cdr->rated_price;
+ $error = $cdr->set_status('done');
+ }
+ die $error if $error;
+ $formatter->append($cdr) unless $usage_nozero && $cdr->rated_price == 0;
+
+ $cdr_search->adjust(1) if $cdr->freesidestatus eq 'rated';
+ } #$cdr
}
$formatter->finish; #writes into $details