[freeside-commits] branch FREESIDE_3_BRANCH updated. c651e310ffbb04c38fd582f874149771efafa5bd
Ivan
ivan at 420.am
Mon Jun 9 17:51:29 PDT 2014
The branch, FREESIDE_3_BRANCH has been updated
via c651e310ffbb04c38fd582f874149771efafa5bd (commit)
from 71f60459dbe9f803c0515bd2e54ef18f4e266fa1 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit c651e310ffbb04c38fd582f874149771efafa5bd
Author: Ivan Kohler <ivan at freeside.biz>
Date: Mon Jun 9 17:51:28 2014 -0700
Wholesale CDR cost re-billing, RT#27555
diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index 4126d5f..3af776b 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -1049,6 +1049,31 @@ sub rate_single_price {
}
+=item rate_cost
+
+Rates an already-rated CDR according to the cost fields from the rate plan.
+
+Returns the amount.
+
+=cut
+
+sub rate_cost {
+ my $self = shift;
+
+ return 0 unless $self->rated_ratedetailnum;
+
+ my $rate_detail =
+ qsearchs('rate_detail', { 'ratedetailnum' => $self->rated_ratedetailnum } );
+
+ return $rate_detail->min_cost if $self->rated_granularity == 0;
+
+ my $minutes = $self->rated_seconds / 60;
+ my $charge = $rate_detail->conn_cost + $minutes * $rate_detail->min_cost;
+
+ sprintf('%.2f', $charge + .00001 );
+
+}
+
=item cdr_termination [ TERMPART ]
=cut
diff --git a/FS/FS/part_pkg/agent_cdr.pm b/FS/FS/part_pkg/agent_cdr.pm
new file mode 100644
index 0000000..8c97a01
--- /dev/null
+++ b/FS/FS/part_pkg/agent_cdr.pm
@@ -0,0 +1,198 @@
+package FS::part_pkg::agent_cdr;
+use base qw( FS::part_pkg::recur_Common );
+
+#kind of glommed together from cdr_termination, agent, voip_cdr
+# some false laziness w/ all of them
+
+use strict;
+use vars qw( $DEBUG $me %info );
+use FS::Record qw( qsearch );
+use FS::PagedSearch qw( psearch );
+use FS::agent;
+use FS::cust_main;
+use FS::cdr;
+
+$DEBUG = 0;
+
+$me = '[FS::part_pkg::agent_cdr]';
+
+%info = (
+ 'name' => 'Wholesale CDR cost billing, for master customers of an agent.',
+ 'shortname' => 'Whilesale CDR cost billing for agent.',
+ 'inherit_fields' => [ 'prorate_Mixin', 'global_Mixin' ],
+ 'fields' => { #false laziness w/cdr_termination
+
+ #false laziness w/flat.pm
+ 'recur_temporality' => { 'name' => 'Charge recurring fee for period',
+ 'type' => 'select',
+ 'select_options' => \%temporalities,
+ },
+
+ 'cutoff_day' => { 'name' => 'Billing Day (1 - 28) for prorating or '.
+ 'subscription',
+ 'default' => '1',
+ },
+ 'recur_method' => { 'name' => 'Recurring fee method',
+ #'type' => 'radio',
+ #'options' => \%recur_method,
+ 'type' => 'select',
+ 'select_options' => \%FS::part_pkg::recur_Common::recur_method,
+ },
+
+ #false laziness w/voip_cdr.pm
+ 'output_format' => { 'name' => 'CDR invoice display format',
+ 'type' => 'select',
+ 'select_options' => { FS::cdr::invoice_formats() },
+ 'default' => 'simple2', #XXX test
+ },
+
+ 'usage_section' => { 'name' => 'Section in which to place separate usage charges',
+ },
+
+ 'summarize_usage' => { 'name' => 'Include usage summary with recurring charges when usage is in separate section',
+ 'type' => 'checkbox',
+ },
+
+ 'usage_mandate' => { 'name' => 'Always put usage details in separate section',
+ 'type' => 'checkbox',
+ },
+ #eofalse
+
+ },
+
+ 'fieldorder' => [ qw( recur_temporality recur_method cutoff_day ),
+ FS::part_pkg::prorate_Mixin::fieldorder,
+ qw(
+ output_format usage_section summarize_usage usage_mandate
+ )
+ ],
+
+ 'weight' => 53,
+
+);
+
+sub calc_recur {
+ my $self, $cust_pkg, $sdate, $details, $param ) = @_;
+
+ #my $last_bill = $cust_pkg->last_bill;
+ my $last_bill = $cust_pkg->get('last_bill'); #->last_bill falls back to setup
+
+ return 0
+ if $self->recur_temporality eq 'preceding'
+ && ( $last_bill eq '' || $last_bill == 0 );
+
+ my $charges = 0;
+
+ #CDR calculations
+
+ #false laziness w/agent.pm
+ #almost always just one,
+ #unless you have multiple agents with same master customer0
+ my @agents = qsearch('agent', { 'agent_custnum' => $cust_pkg->custnum } );
+
+ foreach my $agent (@agents) {
+
+ warn "$me billing wholesale CDRs for agent ". $agent->agent. "\n"
+ if $DEBUG;
+
+ #not the most efficient to load them all into memory,
+ #but good enough for our current needs
+ my @cust_main = qsearch('cust_main', { 'agentnum' => $agent->agentnum } );
+
+ foreach my $cust_main (@cust_main) {
+
+ warn "$me billing agent wholesale CDRs for ". $cust_main->name_short. "\n"
+ if $DEBUG;
+
+ #eofalse laziness w/agent.pm
+
+ my @svcnum = ();
+ foreach my $cust_pkg ( $cust_main->cust_pkg ) {
+ push @svcnum, map $_->svcnum, $cust_pkg->cust_svc( svcdb=>'svc_phone' );
+ }
+
+ next unless @svcnum;
+
+ #false laziness w/cdr_termination
+
+ my $termpart = 1; #or from an option -- we're not termination, we're wholesale? for now, use one or the other
+
+ #false lazienss w/search/cdr.html (i should be a part_termination method)
+ my $where_term =
+ "( cdr.acctid = cdr_termination.acctid AND termpart = $termpart ) ";
+ #my $join_term = "LEFT JOIN cdr_termination ON ( $where_term )";
+ my $extra_sql =
+ "AND NOT EXISTS ( SELECT 1 FROM cdr_termination WHERE $where_term )";
+
+ #eofalse laziness w/cdr_termination.pm
+
+ #false laziness w/ svc_phone->psearch_cdrs, kinda
+ my $cdr_search = psearch({
+ 'table' => 'cdr',
+ #'addl_from' => $join_term,
+ 'hashref' => {},
+ 'extra_sql' => " WHERE freesidestatus IN ( 'rated', 'done' ) ".
+ " AND svcnum IN (". join(',', @svcnum). ") ".
+ $extra_sql,
+ 'order_by' => 'ORDER BY startdate FOR UPDATE ',
+
+ });
+
+ #false laziness w/voip_cdr
+ $cdr_search->limit(1000);
+ $cdr_search->increment(0); #because we're adding cdr_termination as we go?
+ while ( my $cdr = $cdr_search->fetch ) {
+
+ my $cost = $cdr->rate_cost;
+ #XXX exception handling? return undef? (and err?) ref to a scalar err?
+
+ #false laziness w/cdr_termination
+
+ #add a cdr_termination record and the charges
+
+ my $cdr_termination = new FS::cdr_termination {
+ 'acctid' => $cdr->acctid,
+ 'termpart' => $termpart,
+ 'rated_price' => $cost,
+ 'status' => 'done',
+ };
+
+ my $error = $cdr_termination->insert;
+ die $error if $error; #next if $error; #or just skip this one??? why?
+
+ $charges += $cost;
+
+ # and add a line to the invoice
+
+ my $call_details = $cdr->downstream_csv( 'format' => $output_format,
+ 'charge' => $cost,
+ );
+ my $classnum = ''; #usage class?
+
+ #option to turn off? or just use squelch_cdr for the customer probably
+ push @$details, [ 'C', $call_details, $cost, $classnum ];
+
+ #eofalse laziness w/cdr_termination
+
+ }
+
+ }
+
+ }
+
+ #eo CDR calculations
+
+ $charges += ($cust_pkg->quantity || 1) * $self->calc_recur_Common(@_);
+
+ $charges;
+}
+
+sub can_discount { 0; }
+
+#? sub hide_svc_detail { 1; }
+
+sub is_free { 0; }
+
+sub can_usageprice { 0; }
+
+1;
-----------------------------------------------------------------------
Summary of changes:
FS/FS/cdr.pm | 25 ++++++
FS/FS/part_pkg/agent_cdr.pm | 198 +++++++++++++++++++++++++++++++++++++++++++
2 files changed, 223 insertions(+)
create mode 100644 FS/FS/part_pkg/agent_cdr.pm
More information about the freeside-commits
mailing list