[freeside-commits] branch master updated. 83e442de6a041fa3b7580d53912eeb1490ddf47c

Mark Wells mark at 420.am
Fri Oct 10 16:36:17 PDT 2014


The branch, master has been updated
       via  83e442de6a041fa3b7580d53912eeb1490ddf47c (commit)
       via  2a26e4616da323e083c941e9a8c3d2b35377bc3f (commit)
      from  4dd8ad334bd0aed98c4119b3199b955ef4782cb1 (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 83e442de6a041fa3b7580d53912eeb1490ddf47c
Author: Mark Wells <mark at freeside.biz>
Date:   Fri Oct 10 16:36:07 2014 -0700

    upstream-markup call rating and global default rates, #30633

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index ba39d80..0b82f91 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -4808,9 +4808,10 @@ sub tables_hashref {
 
     'rate' => {
       'columns' => [
-        'ratenum',   'serial',     '',      '', '', '', 
-        'ratename', 'varchar',     '', $char_d, '', '', 
-        'agentnum',     'int', 'NULL',      '', '', '',
+        'ratenum',          'serial',     '', '', '', '', 
+        'ratename',        'varchar', '',$char_d, '', '', 
+        'agentnum',            'int', 'NULL', '', '', '',
+        'default_detailnum',   'int', 'NULL', '', '', '',
       ],
       'primary_key' => 'ratenum',
       'unique'      => [],
@@ -4827,7 +4828,7 @@ sub tables_hashref {
         'ratedetailnum',   'serial',  '',     '',      '', '', 
         'ratenum',         'int',     '',     '',      '', '', 
         'orig_regionnum',  'int', 'NULL',     '',      '', '', 
-        'dest_regionnum',  'int',     '',     '',      '', '', 
+        'dest_regionnum',  'int', 'NULL',     '',      '', '', 
         'min_included',    'int',     '',     '',      '', '', 
         'conn_charge',     'decimal', '', '10,4', '0.0000', '',
         'conn_cost',       'decimal', '', '10,4', '0.0000', '',
@@ -4839,6 +4840,8 @@ sub tables_hashref {
         'classnum',        'int', 'NULL',     '',       '', '', 
         'cdrtypenum',      'int', 'NULL',     '',       '', '',
         'region_group',   'char', 'NULL',      1,       '', '', 
+        'upstream_mult_charge',  'decimal',  '', '10,4', '0.0000', '',
+        'upstream_mult_cost',    'decimal',  '', '10,4', '0.0000', '',
       ],
       'primary_key'  => 'ratedetailnum',
       'unique'       => [ [ 'ratenum', 'orig_regionnum', 'dest_regionnum' ] ],
diff --git a/FS/FS/cdr.pm b/FS/FS/cdr.pm
index 9859dfa..7a5668d 100644
--- a/FS/FS/cdr.pm
+++ b/FS/FS/cdr.pm
@@ -799,8 +799,8 @@ sub rate_prefix {
 
   }
 
+  my $regionnum = $rate_detail->dest_regionnum;
   my $rate_region = $rate_detail->dest_region;
-  my $regionnum = $rate_region->regionnum;
   warn "  found rate for regionnum $regionnum ".
        "and rate detail $rate_detail\n"
     if $DEBUG;
@@ -842,6 +842,11 @@ sub rate_prefix {
   my $charge = 0;
   my $connection_charged = 0;
 
+  # before doing anything else, if there's an upstream multiplier and 
+  # an upstream price, add that to the charge. (usually the rate detail 
+  # will then have a minute charge of zero, but not necessarily.)
+  $charge += ($self->upstream_price || 0) * $rate_detail->upstream_mult_charge;
+
   my $etime;
   while($seconds_left) {
     my $ratetimenum = $rate_detail->ratetimenum; # may be empty
@@ -989,7 +994,7 @@ sub rate_prefix {
     $price,
     $opt{'svcnum'},
     'rated_pretty_dst'    => $pretty_dst,
-    'rated_regionname'    => $rate_region->regionname,
+    'rated_regionname'    => ($rate_region ? $rate_region->regionname : ''),
     'rated_seconds'       => $rated_seconds, #$seconds,
     'rated_granularity'   => $rate_detail->sec_granularity, #$granularity
     'rated_ratedetailnum' => $rate_detail->ratedetailnum,
@@ -1073,10 +1078,15 @@ sub rate_cost {
   my $rate_detail =
     qsearchs('rate_detail', { 'ratedetailnum' => $self->rated_ratedetailnum } );
 
-  return $rate_detail->min_cost if $self->rated_granularity == 0;
+  my $charge = 0;
+  $charge += ($self->upstream_price || 0) * ($rate_detail->upstream_mult_cost);
 
-  my $minutes = $self->rated_seconds / 60;
-  my $charge = $rate_detail->conn_cost + $minutes * $rate_detail->min_cost;
+  if ( $self->rated_granularity == 0 ) {
+    $charge += $rate_detail->min_cost;
+  } else {
+    my $minutes = $self->rated_seconds / 60;
+    $charge += $rate_detail->conn_cost + $minutes * $rate_detail->min_cost;
+  }
 
   sprintf('%.2f', $charge + .00001 );
 
diff --git a/FS/FS/part_pkg/agent_cdr.pm b/FS/FS/part_pkg/agent_cdr.pm
index 55792f2..a638b5b 100644
--- a/FS/FS/part_pkg/agent_cdr.pm
+++ b/FS/FS/part_pkg/agent_cdr.pm
@@ -23,7 +23,7 @@ tie my %temporalities, 'Tie::IxHash',
 
 %info = (
   'name'      => 'Wholesale CDR cost billing, for master customers of an agent.',
-  'shortname' => 'Whilesale CDR cost billing for agent.',
+  'shortname' => 'Wholesale CDR cost billing for agent',
   'inherit_fields' => [ 'prorate_Mixin', 'global_Mixin' ],
   'fields' => { #false laziness w/cdr_termination
 
@@ -177,7 +177,11 @@ sub calc_recur {
         my $classnum = ''; #usage class?
 
        #option to turn off?  or just use squelch_cdr for the customer probably
-        push @$details, [ 'C', $call_details, $cost, $classnum ];
+        # XXX use detail_format for this at some point
+        push @$details, { 'format'    => 'C',
+                          'detail'    => $call_details,
+                          'amount'    => $cost,
+                          'classnum'  => $classnum };
 
         #eofalse laziness w/cdr_termination
 
diff --git a/FS/FS/rate.pm b/FS/FS/rate.pm
index aef9d8b..9a5b905 100644
--- a/FS/FS/rate.pm
+++ b/FS/FS/rate.pm
@@ -46,6 +46,16 @@ Rate name
 
 Optional agent (see L<FS::agent>) for agent-virtualized rates.
 
+=item default_detailnum 
+
+Optional rate detail to apply when a call doesn't match any region in the 
+rate plan. If this is not set, the call will either be left unrated (though
+it may still be processed under a different pricing addon package), or be 
+marked as 'skipped', or throw a fatal error, depending on the setting of 
+the 'ignore_unrateable' package option.
+
+=item 
+
 =back
 
 =head1 METHODS
@@ -268,6 +278,7 @@ sub check {
        $self->ut_numbern('ratenum')
     || $self->ut_text('ratename')
     #|| $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum')
+    || $self->ut_numbern('default_detailnum')
   ;
   return $error if $error;
 
@@ -277,8 +288,8 @@ sub check {
 =item dest_detail REGIONNUM | RATE_REGION_OBJECTD | HASHREF
 
 Returns the rate detail (see L<FS::rate_detail>) for this rate to the
-specificed destination, or the empty string if no rate can be found for
-the given destination.
+specificed destination. If no rate can be found, returns the default 
+rate if there is one, and an empty string otherwise.
 
 Destination can be specified as an FS::rate_detail object or regionnum
 (see L<FS::rate_detail>), or as a hashref containing the following keys:
@@ -379,8 +390,8 @@ sub dest_detail {
   foreach (@details) {
     return $_ if $_->ratetimenum eq '';
   }
-  # found nothing
-  return;
+  # if still nothing, return the global default rate for this plan
+  return $self->default_detail;
 }
 
 =item rate_detail
@@ -389,6 +400,18 @@ Returns all region-specific details  (see L<FS::rate_detail>) for this rate.
 
 =back
 
+=item default_detail
+
+Returns the default rate detail, if there is one.
+
+=cut
+
+sub default_detail {
+  my $self = shift;
+  $self->default_detailnum ?
+    FS::rate_detail->by_key($self->default_detailnum) : ''
+}
+
 =head1 SUBROUTINES
 
 =over 4
diff --git a/FS/FS/rate_detail.pm b/FS/FS/rate_detail.pm
index d81d9db..d50c89f 100644
--- a/FS/FS/rate_detail.pm
+++ b/FS/FS/rate_detail.pm
@@ -60,6 +60,13 @@ inherits from FS::Record.  The following fields are currently supported:
 
 =item region_group - Group in region group for rate plan
 
+=item upstream_mult_charge - the multiplier to apply to the upstream price. 
+Defaults to zero, and should stay zero unless this rate is intended to include
+a markup on pre-rated CDRs.
+
+=item upstream_mult_cost - the multiplier to apply to the upstream price to
+calculate the wholesale cost.
+
 =back
 
 =head1 METHODS
@@ -124,7 +131,7 @@ sub check {
        $self->ut_numbern('ratedetailnum')
     || $self->ut_foreign_key('ratenum', 'rate', 'ratenum')
     || $self->ut_foreign_keyn('orig_regionnum', 'rate_region', 'regionnum' )
-    || $self->ut_foreign_key('dest_regionnum', 'rate_region', 'regionnum' )
+    || $self->ut_foreign_keyn('dest_regionnum', 'rate_region', 'regionnum' )
     || $self->ut_number('min_included')
 
     #|| $self->ut_money('min_charge')
@@ -138,6 +145,9 @@ sub check {
 
     || $self->ut_foreign_keyn('classnum', 'usage_class', 'classnum' )
     || $self->ut_enum('region_group',    [ '', 'Y' ])
+
+    || $self->ut_floatn('upstream_mult_charge')
+    || $self->ut_floatn('upstream_mult_cost')
   ;
   return $error if $error;
 
@@ -182,10 +192,11 @@ with this call plan rate.
 
 sub dest_regionname {
   my $self = shift;
-  $self->dest_region->regionname;
+  my $dest_region = $self->dest_region;
+  $dest_region ? $dest_region->regionname : 'Global default';
 }
 
-=item dest_regionname
+=item dest_prefixes_short
 
 Returns a short list of the prefixes for the destination region
 (see L<FS::rate_region>) associated with this call plan rate.
@@ -194,7 +205,8 @@ Returns a short list of the prefixes for the destination region
 
 sub dest_prefixes_short {
   my $self = shift;
-  $self->dest_region->prefixes_short;
+  my $dest_region = $self->dest_region;
+  $dest_region ? $dest_region->prefixes_short : '';
 }
 
 =item rate_time
diff --git a/httemplate/edit/elements/rate_detail.html b/httemplate/edit/elements/rate_detail.html
index 14b5211..7b5ec31 100644
--- a/httemplate/edit/elements/rate_detail.html
+++ b/httemplate/edit/elements/rate_detail.html
@@ -47,34 +47,85 @@ with row headers showing the region name and prefixes.
 %   }
 %   foreach my $rate_time (@rate_time, '') {
   <TD>
-%     my $detail = $details[$row][$col];
-%     if($detail) {
+    <& .detail_box,
+      detail      => $details[$row][$col],
+      ratetimenum => ($rate_time ? $rate_time->ratetimenum : ''),
+      cdrtypenum  => $cdrtypenum,
+      regionnum   => $region->regionnum,
+      ratenum     => $rate->ratenum
+    &>
+%     $col++;
+  </TD>
+%   } # foreach @rate_time
+</TR>
+%   $row++;
+% }# foreach @rate_region
+% if ( !$opt{regionnum} ) {
+%# global default
+<TR>
+  <TD COLSPAN=2 STYLE="padding-top: 10px">
+    <B>Global default</B> (for calls not matching any prefix)
+  </TD>
+  <TD STYLE="padding-top: 10px">
+%   # default rate: set a null region
+    <B>
+    <& .detail_box,
+      detail      => $rate->default_detail,
+      ratetimenum => '',
+      cdrtypenum  => '',
+      regionnum   => '',
+      ratenum     => $rate->ratenum
+    &>
+    </B>
+  </TD>
+% }
+</TABLE>
+<%def .detail_box>
+<%args>
+$detail => undef,
+$ratetimenum
+$cdrtypenum
+$regionnum
+$ratenum
+</%args>
+% if ($detail) {
       <TABLE CLASS="inv" STYLE="border:none">
-      <TR><TD><% edit_link($detail) %><% $money_char.$detail->min_charge %>
+      <TR><TD><% edit_link($detail) %>
+%   if ( $detail->min_charge > 0 or $detail->conn_charge > 0) {
+              <% $money_char.$detail->min_charge %>
               <% $detail->sec_granularity ? ' / minute':' / call' %>
 %             if ( $detail->min_cost ) {
                 (<% $money_char.$detail->min_cost %> cost)
 %             }
+%     if ( $detail->upstream_mult_charge > 0
+%          or $detail->upstream_mult_cost > 0) {
+              <BR>+ 
+%     }
+%   }
+%   if ( $detail->upstream_mult_charge > 0 
+%        or $detail->upstream_mult_cost > 0) {
+              <% $detail->upstream_mult_charge %> × upstream price
+%             if ( $detail->upstream_mult_cost > 0 ) {
+              (<% $detail->upstream_mult_cost %> cost)
+%             }
+%   }
+%   if ( $detail->upstream_mult_charge == 0
+%        and $detail->min_charge == 0 
+%        and $detail->conn_charge == 0 ) {
+              Free
+%   }
       <% $edit_hint %></A>
       </TD></TR>
       <% granularity_detail($detail) %>
       <% min_included_detail($detail) %>
       <% conn_charge_detail($detail) %>
-      <TR><TD><% ( $rate_time || $cdrtypenum ) ? delete_link($detail) : '' %>
+      <TR><TD><% ( $ratetimenum || $cdrtypenum ) ? delete_link($detail) : '' %>
       </TD></TR>
     </TABLE>
-%     }
-%     else { #!$detail
-    <% add_link($rate, $region, $rate_time, $cdrtypenum) %>
-%     }
-%     $col++;
-  </TD>
-%   } # foreach @rate_time
-</TR>
-%   $row++;
-% }# foreach @rate_region
-</TABLE>
-
+% } else {
+    <% add_link($ratenum, $regionnum, $ratetimenum, $cdrtypenum) %>
+% }
+</%def>
 <%once>
 
 tie my %granularity, 'Tie::IxHash', FS::rate_detail::granularities();
@@ -95,25 +146,27 @@ sub edit_link {
   include( '/elements/popup_link_onclick.html',
              'action'      => "${p}edit/rate_detail.html?$ratedetailnum",
              'actionlabel' => 'Edit rate',
-             'height'      => 460,
+             'height'      => 550,
+             'width'       => 580,
              #default# 'width'       => 540,
              #default# 'color'       => '#333399',
          ) . '">'
 }
 
 sub add_link {
-  my ($rate, $region, $rate_time, $cdrtypenum) = @_;
+  my ($ratenum, $regionnum, $ratetimenum, $cdrtypenum) = @_;
   '<A HREF="javascript:void(0);" onclick="'.
   include( '/elements/popup_link_onclick.html',
              'action'      => "${p}edit/rate_detail.html?ratenum=".
-                                  $rate->ratenum.
+                                  $ratenum.
                                ';dest_regionnum='.
-                                  $region->regionnum.
+                                  $regionnum.
                                ';ratetimenum='.
-                                 ($rate_time ? $rate_time->ratetimenum : '').
+                                 ($ratetimenum || '').
                                ";cdrtypenum=$cdrtypenum",
              'actionlabel' => 'Add rate',
-             'height'      => 460,
+             'width'       => 580,
+             'height'      => 550,
              ).'">'.small('(add)').'</A>'
 }
 
@@ -133,7 +186,10 @@ sub delete_link {
 
 sub granularity_detail {
   my $rate_detail = shift;
-  if($rate_detail->sec_granularity != 60 && $rate_detail->sec_granularity > 0) {
+  if(
+      $rate_detail->sec_granularity != 60 
+      && $rate_detail->sec_granularity > 0
+      && $rate_detail->min_charge > 0) {
     '<TR><TD>'.
     small('in '.$granularity{$rate_detail->sec_granularity}.' increments').
     '</TD></TR>';
diff --git a/httemplate/edit/process/rate_detail.html b/httemplate/edit/process/rate_detail.html
index 6200d61..0709d50 100644
--- a/httemplate/edit/process/rate_detail.html
+++ b/httemplate/edit/process/rate_detail.html
@@ -1,13 +1,35 @@
-<% include( 'elements/process.html',
-              'table' => 'rate_detail',
-              'popup_reload' => 'Rate changed', #a popup "parent reload" for now
+<& elements/process.html,
+  'table' => 'rate_detail',
+  'popup_reload' => 'Rate changed', #a popup "parent reload" for now
               #someday change the individual element and go away instead
-          )
-%>
+  'noerror_callback' => $set_default_detail
+&>
 <%init>
 
 my $conf = new FS::Conf;
 die "access denied"
   unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
 
+my $set_default_detail = sub {
+  my ($cgi, $rate_detail) = @_;
+warn Dumper $rate_detail;
+  if (!$rate_detail->dest_regionnum) {
+    # then this is a global default rate
+    my $rate = $rate_detail->rate;
+    if ($rate->default_detailnum) {
+      if ($rate->default_detailnum == $rate_detail->ratedetailnum) {
+        return;
+      } else {
+        # there's somehow an existing default rate. remove it.
+        my $old_default = $rate->default_detail;
+        my $error = $old_default->delete;
+        die "$error (removing old default rate)\n" if $error;
+      }
+    }
+    $rate->set('default_detailnum' => $rate_detail->ratedetailnum);
+    my $error = $rate->replace;
+    die "$error (setting default rate)\n" if $error;
+  }
+};
+
 </%init>
diff --git a/httemplate/edit/rate_detail.html b/httemplate/edit/rate_detail.html
index 0de6ecc..3e80072 100644
--- a/httemplate/edit/rate_detail.html
+++ b/httemplate/edit/rate_detail.html
@@ -15,6 +15,8 @@
                    'conn_cost'           => 'Wholesale connection cost',
                    'min_cost'            => 'Wholesale cost per minute/call',
                    'classnum'            => 'Usage class',
+                   'upstream_mult_charge'=> 'Upstream multiplier (retail)',
+                   'upstream_mult_cost'  => 'Upstream multiplier (cost)',
                  },
      'fields' => [
                    { field=>'ratenum',             type=>'hidden', },
@@ -46,13 +48,15 @@
                      labels        => \%granularity,
                      disable_empty => 1,
                    },
-                   { field         =>'classnum',
-                     type          =>'select-table',
-                     table         =>'usage_class',
-                     name_col      =>'classname',
-                     empty_label   =>'(default)',
-                     hashref        =>{ disabled => '' },
+                   { field         => 'classnum',
+                     type          => 'select-table',
+                     table         => 'usage_class',
+                     name_col      => 'classname',
+                     empty_label   => '(default)',
+                     hashref       => { disabled => '' },
                    },
+                   { field         => 'upstream_mult_charge', type => 'text', },
+                   { field         => 'upstream_mult_cost', type => 'text', },
 
                  ],
      'new_hashref_callback' => sub {
@@ -62,6 +66,8 @@
           cdrtypenum     => scalar($cgi->param('cdrtypenum')),
           min_included   => 0,
           conn_charge    => 0,
+          upstream_mult_charge  => 0,
+          upstream_mult_cost    => 0,
         }
       },
    )
@@ -85,8 +91,8 @@ if (    $keywords                    =~ /^(\d+)$/
      || $cgi->param('ratedetailnum') =~ /^(\d+)$/ ) {
   my $rate_detail = qsearchs('rate_detail', { 'ratedetailnum' => $1 } )
     or die "unknown ratedetailnum $1";
-  $name =
-    $rate_detail->rate->ratename. ' rate for '. $rate_detail->dest_regionname;
+  $name = $rate_detail->rate->ratename. ' rate for '. 
+          ($rate_detail->dest_regionname || 'global default');
 }
 
 #sec_granularity should default to 60!  for new rates when this gets used for em

commit 2a26e4616da323e083c941e9a8c3d2b35377bc3f
Author: Mark Wells <mark at freeside.biz>
Date:   Fri Oct 10 14:48:18 2014 -0700

    fix unprovisioning of services when export_delete creates a queue job, #13971

diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 4d6c2e9..ba39d80 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -4151,9 +4151,9 @@ sub tables_hashref {
                           [ 'job' ], [ 'svcnum' ], [ 'custnum' ], [ 'status' ],
                         ],
       'foreign_keys' => [
-                          { columns    => [ 'svcnum' ],
-                            table      => 'cust_svc',
-                          },
+#                          { columns    => [ 'svcnum' ],
+#                            table      => 'cust_svc',
+#                          },
                           { columns    => [ 'custnum' ],
                             table      => 'cust_main',
                           },

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/Schema.pm                           |   17 +++--
 FS/FS/cdr.pm                              |   20 ++++--
 FS/FS/part_pkg/agent_cdr.pm               |    8 ++-
 FS/FS/rate.pm                             |   31 +++++++--
 FS/FS/rate_detail.pm                      |   20 ++++--
 httemplate/edit/elements/rate_detail.html |  102 ++++++++++++++++++++++-------
 httemplate/edit/process/rate_detail.html  |   32 +++++++--
 httemplate/edit/rate_detail.html          |   22 ++++---
 8 files changed, 194 insertions(+), 58 deletions(-)




More information about the freeside-commits mailing list