[freeside-commits] branch master updated. 8861d46820af163c7de7839178b6120c9b32ab2c

Ivan ivan at 420.am
Wed Jan 8 17:23:08 PST 2014


The branch, master has been updated
       via  8861d46820af163c7de7839178b6120c9b32ab2c (commit)
       via  49809d3653e7ac4951d36716dce3cd25ba9c3728 (commit)
       via  4427ad71b12bf27eac2a05d88141a82f9372d03f (commit)
      from  76275769ed7ea66b154aef4d2dd00120a53196df (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 8861d46820af163c7de7839178b6120c9b32ab2c
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Wed Jan 8 17:23:05 2014 -0800

    time/data/etc. unit pricing add-ons, RT#24392

diff --git a/FS/FS.pm b/FS/FS.pm
index 3ff3656..afea6f1 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -257,6 +257,8 @@ L<FS::part_pkg_msgcat> - Package definition localization class
 
 L<FS::part_pkg_usageprice> - Package definition usage pricing add-on class
 
+L<FS::cust_pkg_usageprice> - Customer package usage pricing add-on class
+
 L<FS::part_pkg_currency> - Package definition local currency prices
 
 L<FS::currency_exchange> - Currency exchange rates
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm
index 276c8c0..62e5755 100644
--- a/FS/FS/Mason.pm
+++ b/FS/FS/Mason.pm
@@ -367,6 +367,7 @@ if ( -e $addl_handler_use_file ) {
   use FS::conferencing_quality;
   use FS::svc_video;
   use FS::part_pkg_usageprice;
+  use FS::cust_pkg_usageprice;
   # Sammath Naur
 
   if ( $FS::Mason::addl_handler_use ) {
diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm
index 5833d86..870ac4f 100644
--- a/FS/FS/Schema.pm
+++ b/FS/FS/Schema.pm
@@ -3056,6 +3056,26 @@ sub tables_hashref {
                         ],
     },
 
+    'cust_pkg_usageprice' => {
+      'columns' => [
+        'usagepricenum', 'serial',      '',      '', '', '',
+        'pkgnum',           'int',      '',      '', '', '',
+        'usagepricepart',   'int',      '',      '', '', '',
+        'quantity',         'int',      '',      '', '', '',
+      ],
+      'primary_key'  => 'usagepricenum',
+      'unique'       => [ [ 'pkgnum', 'usagepricepart' ] ],
+      'index'        => [ [ 'pkgnum' ] ],
+      'foreign_keys' => [
+                          { columns    => [ 'pkgnum' ],
+                            table      => 'cust_pkg',
+                          },
+                          { columns    => [ 'usagepricepart' ],
+                            table      => 'part_pkg_usageprice',
+                          },
+                        ],
+    },
+
     'part_pkg_link' => {
       'columns' => [
         'pkglinknum',  'serial',   '',      '', '', '',
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index afdd41d..97354d4 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -267,6 +267,10 @@ orders.  (Currently this includes: intro periods when delay_setup is on.)
 
 cust_pkg_option records will be created
 
+=item cust_pkg_usageprice
+
+Array reference of cust_pkg_usageprice objects, will be inserted
+
 =item ticket_subject
 
 a ticket will be added to this customer with this subject
@@ -353,6 +357,17 @@ sub insert {
                       'params'       => $self->refnum,
                     );
 
+  if ( $self->hashref->{cust_pkg_usageprice} ) {
+    for my $cust_pkg_usageprice ( @{ $self->hashref->{cust_pkg_usageprice} } ) {
+      $cust_pkg_usageprice->pkgnum( $self->pkgnum );
+      my $error = $cust_pkg_usageprice->insert;
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return $error;
+      }
+    }
+  }
+
   if ( $self->discountnum ) {
     my $error = $self->insert_discount();
     if ( $error ) {
diff --git a/FS/FS/cust_pkg_usageprice.pm b/FS/FS/cust_pkg_usageprice.pm
new file mode 100644
index 0000000..5380081
--- /dev/null
+++ b/FS/FS/cust_pkg_usageprice.pm
@@ -0,0 +1,117 @@
+package FS::cust_pkg_usageprice;
+use base qw( FS::Record );
+
+use strict;
+#use FS::Record qw( qsearch qsearchs );
+
+=head1 NAME
+
+FS::cust_pkg_usageprice - Object methods for cust_pkg_usageprice records
+
+=head1 SYNOPSIS
+
+  use FS::cust_pkg_usageprice;
+
+  $record = new FS::cust_pkg_usageprice \%hash;
+  $record = new FS::cust_pkg_usageprice { 'column' => 'value' };
+
+  $error = $record->insert;
+
+  $error = $new_record->replace($old_record);
+
+  $error = $record->delete;
+
+  $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_pkg_usageprice object represents an specific customer package usage
+pricing add-on.  FS::cust_pkg_usageprice inherits from FS::Record.  The
+following fields are currently supported:
+
+=over 4
+
+=item usagepricenum
+
+primary key
+
+=item pkgnum
+
+pkgnum
+
+=item usagepricepart
+
+usagepricepart
+
+=item quantity
+
+quantity
+
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record.  To add the record to the database, see L<"insert">.
+
+Note that this stores the hash reference, not a distinct copy of the hash it
+points to.  You can ask the object for a copy with the I<hash> method.
+
+=cut
+
+# the new method can be inherited from FS::Record, if a table method is defined
+
+sub table { 'cust_pkg_usageprice'; }
+
+=item insert
+
+Adds this record to the database.  If there is an error, returns the error,
+otherwise returns false.
+
+=item delete
+
+Delete this record from the database.
+
+=item replace OLD_RECORD
+
+Replaces the OLD_RECORD with this one in the database.  If there is an error,
+returns the error, otherwise returns false.
+
+=item check
+
+Checks all fields to make sure this is a valid record.  If there is
+an error, returns the error, otherwise returns false.  Called by the insert
+and replace methods.
+
+=cut
+
+sub check {
+  my $self = shift;
+
+  my $error = 
+    $self->ut_numbern('usagepricenum')
+    || $self->ut_number('pkgnum')
+    || $self->ut_number('usagepricepart')
+    || $self->ut_number('quantity')
+  ;
+  return $error if $error;
+
+  $self->SUPER::check;
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::Record>
+
+=cut
+
+1;
+
diff --git a/FS/FS/part_pkg_usageprice.pm b/FS/FS/part_pkg_usageprice.pm
index 88e3870..9c3b1be 100644
--- a/FS/FS/part_pkg_usageprice.pm
+++ b/FS/FS/part_pkg_usageprice.pm
@@ -121,8 +121,21 @@ sub check {
   $self->SUPER::check;
 }
 
+=item target_info
+
+Returns a hash reference of information about the target of this object.
+Keys are "label" and "multiplier".
+
+=cut
+
+sub target_info {
+  my $self = shift;
+  $self->targets->{$self->target};
+}
+
 =item targets
 
+(Class method)
 Returns a hash reference.  Keys are possible values for the "target" field.
 Values are hash references with "label" and "multiplier" keys.
 
diff --git a/FS/MANIFEST b/FS/MANIFEST
index 3bed3ee..315e62c 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -747,3 +747,5 @@ FS/svc_video.pm
 t/svc_video.t
 FS/part_pkg_usageprice.pm
 t/part_pkg_usageprice.t
+FS/cust_pkg_usageprice.pm
+t/cust_pkg_usageprice.t
diff --git a/FS/t/cust_pkg_usageprice.t b/FS/t/cust_pkg_usageprice.t
new file mode 100644
index 0000000..2e057ed
--- /dev/null
+++ b/FS/t/cust_pkg_usageprice.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::cust_pkg_usageprice;
+$loaded=1;
+print "ok 1\n";
diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi
index b073866..574cf7a 100755
--- a/httemplate/browse/part_pkg.cgi
+++ b/httemplate/browse/part_pkg.cgi
@@ -278,9 +278,8 @@ push @fields, sub {
       ),
     ],
     (
-      map { my $amount = $_->amount
-              / (FS::part_pkg_usageprice->targets->{$_->target}{multiplier}||1);
-            my $label = FS::part_pkg_usageprice->targets->{$_->target}{label};
+      map { my $amount = $_->amount / ($_->target_info->{multiplier} || 1);
+            my $label = $_->target_info->{label};
             [
               { data    => "Plus $money_char". $_->price. ' '.
                            ( $_->action eq 'increment' ? 'per' : 'for' ).
diff --git a/httemplate/edit/process/quick-cust_pkg.cgi b/httemplate/edit/process/quick-cust_pkg.cgi
index 7dcd232..95c9243 100644
--- a/httemplate/edit/process/quick-cust_pkg.cgi
+++ b/httemplate/edit/process/quick-cust_pkg.cgi
@@ -133,6 +133,21 @@ my %hash = (
 );
 $hash{'custnum'} = $cust_main->custnum if $cust_main;
 
+my @cust_pkg_usageprice = ();
+foreach my $quantity_param ( grep ( $cgi->param($_) && $cgi->param($_) > 0 ),
+                               grep /^usagepricenum(\d+)_quantity$/,
+                                 $cgi->param
+                           )
+{
+  $quantity_param =~ /^usagepricenum(\d+)_quantity$/ or die 'unpossible';
+  my $num = $1;
+  push @cust_pkg_usageprice, new FS::cust_pkg_usageprice {
+    usagepricepart => scalar($cgi->param("usagepricenum${num}_usagepricepart")),
+    quantity       => scalar($cgi->param($quantity_param)),
+  };
+}
+$hash{cust_pkg_usageprice} = \@cust_pkg_usageprice;
+
 if ( $quotationnum ) {
 
   $quotation_pkg = new FS::quotation_pkg \%hash;
diff --git a/httemplate/elements/cust_pkg_usageprice.html b/httemplate/elements/cust_pkg_usageprice.html
new file mode 100644
index 0000000..7290993
--- /dev/null
+++ b/httemplate/elements/cust_pkg_usageprice.html
@@ -0,0 +1,72 @@
+% unless ( $opt{'js_only'} ) {
+
+  <INPUT TYPE="hidden" NAME="<%$name%>" ID="<%$id%>" VALUE="<% $curr_value %>">
+
+  <INPUT TYPE  = "hidden"
+         NAME  = "<%$name%>_usagepricepart"
+         ID    = "<%$id%>_usagepricepart"
+         VALUE = "<% $part_pkg_usageprice->usagepricepart %>"
+  >
+
+  <TABLE STYLE="display:inline">
+    <TR>
+
+%     ###
+%     # action
+%     ###
+      <TD>
+%       # maybe we should be a quantity entry instead of a select?  even more
+%       #  javascript auto-calculation need to display a subtotal & total
+        <SELECT NAME = "<%$name%>_quantity"
+                ID   = "<%$id%>_quantity"
+                <% $onchange %>
+        >
+%         my $info = $part_pkg_usageprice->target_info;
+%         my $amount = $part_pkg_usageprice->amount / ($info->{multiplier}||1);
+          <OPTION VALUE="">Additional <% $info->{label} %>
+%         for (1..100) { #100?  arbitrary.
+            <OPTION VALUE="<% $_ %>"><%
+              $money_char. sprintf('%.2f', $_ * $part_pkg_usageprice->price ).
+              ' '.
+              'for'. #( $part_pkg_usageprice->action eq 'increment' ? 'per' : 'for' ).
+              ' '.
+              ( $_ * $amount ). ' '. $info->{label}
+            %>
+%         }
+        </SELECT>
+      </TD>
+
+    </TR>
+  </TABLE>
+
+% }
+<%init>
+
+#my $targets = FS::part_pkg_usageprice->targets;
+
+my( %opt ) = @_;
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $name = $opt{'element_name'} || $opt{'field'} || 'usagepricenum';
+my $id = $opt{'id'} || $opt{'field'} || 'usagepricenum';
+
+my $curr_value = $opt{'curr_value'} || $opt{'value'};
+
+my $onchange = '';
+if ( $opt{'onchange'} ) {
+  $onchange = $opt{'onchange'};
+  $onchange .= '(this)' unless $onchange =~ /\(\w*\);?$/;
+  $onchange =~ s/\(what\);/\(this\);/g; #ugh, terrible hack.  all onchange
+                                        #callbacks should act the same
+  $onchange = 'onChange="'. $onchange. '"';
+}
+
+my $cust_pkg_usageprice = $curr_value
+  ? qsearchs('cust_pkg_usageprice', { 'usagepricenum' => $curr_value } )
+  : new FS::cust_pkg_usageprice { 'usagepricepart' => $opt{usagepricepart} };
+
+my $part_pkg_usageprice = $cust_pkg_usageprice->part_pkg_usageprice;
+
+</%init>
diff --git a/httemplate/elements/order_pkg.js b/httemplate/elements/order_pkg.js
index 4e41fd6..393b845 100644
--- a/httemplate/elements/order_pkg.js
+++ b/httemplate/elements/order_pkg.js
@@ -21,8 +21,8 @@ function pkg_changed () {
       }
     }
 
-// if this form element exists, then the start date is a future
-// package change date; don't replace it
+    // if this form element exists, then the start date is a future
+    // package change date; don't replace it
     if ( form.delay ) {
       return;
     }
@@ -39,6 +39,8 @@ function pkg_changed () {
       date_button_disabled.style.display = '';
     }
 
+    get_part_pkg_usageprice( opt.value, update_part_pkg_usageprice );
+
   } else {
     form.submitButton.disabled = true;
     if ( discountnum ) { form.discountnum.disabled = true; }
@@ -46,6 +48,69 @@ function pkg_changed () {
   }
 }
 
+function update_part_pkg_usageprice(part_pkg_usageprice) {
+
+  var table = document.getElementById('cust_pkg_usageprice_table');
+
+  // black the current usage price rows
+  for ( var r = table.rows.length - 1; r >= 0; r-- ) {
+    table.deleteRow(r);
+  }
+
+  // add the new usage price rows
+  var rownum = 0;
+  var usagepriceArray = eval('(' + part_pkg_usageprice + ')' );
+  for ( var s = 0; s < usagepriceArray.length; s=s+2 ) {
+    //surely this should be some kind of JSON structure
+    var html       = usagepriceArray[s+0];
+    var javascript = usagepriceArray[s+1];
+
+    // a lot like ("inspiried by") edit/elements/edit.html function spawn_<%$field%>
+
+    // XXX evaluate the javascript
+    //if (window.ActiveXObject) {
+    //  window.execScript(newfunc);
+    //} else { /* (window.XMLHttpRequest) */
+    //  //window.eval(newfunc);
+    //  setTimeout(newfunc, 0);
+    //}
+
+    var row = table.insertRow(rownum++);
+
+    //var label_cell = document.createElement('TD');
+
+    //label_cell.id = '<% $field %>_label' + <%$field%>_fieldnum;
+
+    //label_cell.style.textAlign = "right";
+    //label_cell.style.verticalAlign = "top";
+    //label_cell.style.borderTop = "1px solid black";
+    //label_cell.style.paddingTop = "5px";
+
+    //label_cell.innerHTML = '<% $label %>';
+
+    //row.appendChild(label_cell);
+          
+    var widget_cell = document.createElement('TD');
+
+    //widget_cell.style.borderTop = "1px solid black";
+    widget_cell.style.paddingTop = "3px";
+    widget_cell.colSpan = "2";
+
+    widget_cell.innerHTML = html;
+
+    row.appendChild(widget_cell);
+
+  }
+
+  if ( rownum > 0 ) {
+    document.getElementById('cust_pkg_usageprice_title').style.display = '';
+  } else {
+    document.getElementById('cust_pkg_usageprice_title').style.display = 'none';
+  }
+
+}
+
+
 function standardize_new_location() {
   var form = document.OrderPkgForm;
   var loc = form.locationnum;
diff --git a/httemplate/elements/order_pkg_link.html b/httemplate/elements/order_pkg_link.html
index 0cae492..6e0dd68 100644
--- a/httemplate/elements/order_pkg_link.html
+++ b/httemplate/elements/order_pkg_link.html
@@ -21,6 +21,6 @@ my %optional =
     grep $opt{$_},
       qw( lock_pkgpart lock_locationnum qualnum quotationnum svcpart );
 
-my $height = $opt{'lock_locationnum'} ? 336 : 606;
+my $height = $opt{'lock_locationnum'} ? 470 : 740;
 
 </%init>
diff --git a/httemplate/elements/tr-cust_pkg_usageprice.html b/httemplate/elements/tr-cust_pkg_usageprice.html
new file mode 100644
index 0000000..ccd0631
--- /dev/null
+++ b/httemplate/elements/tr-cust_pkg_usageprice.html
@@ -0,0 +1,24 @@
+%   unless ( $opt{'js_only'} ) {
+
+      <% include('tr-td-label.html', %opt) %>
+        <TD <% $cell_style %>>
+
+%   }
+%
+            <% include( '/elements/cust_pkg_usageprice.html', %opt ) %>
+%
+%   unless ( $opt{'js_only'} ) {
+
+        </TD>
+      </TR>
+
+%   }
+<%init>
+
+my( %opt ) = @_;
+
+my $cell_style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+#$opt{'label'} ||= 'XXX Something';
+
+</%init>
diff --git a/httemplate/misc/detach_pkg.html b/httemplate/misc/detach_pkg.html
index 366bbac..b2dfa38 100755
--- a/httemplate/misc/detach_pkg.html
+++ b/httemplate/misc/detach_pkg.html
@@ -1,7 +1,5 @@
 <& /elements/header-popup.html, mt("Detach Package to New Customer") &>
 
-<SCRIPT TYPE="text/javascript" SRC="../elements/order_pkg.js"></SCRIPT>
-
 <& /elements/error.html &>
 
 <FORM NAME="OrderPkgForm" ACTION="<% $p %>edit/process/detach-cust_pkg.html" METHOD=POST>
diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html
index b06f962..080ba41 100644
--- a/httemplate/misc/order_pkg.html
+++ b/httemplate/misc/order_pkg.html
@@ -5,6 +5,12 @@
    }
 &>
 
+<& /elements/xmlhttp.html,
+              'url'  => $p.'misc/xmlhttp-part_pkg_usageprice.html',
+              'subs' => [ 'get_part_pkg_usageprice' ],
+&>
+
+
 <LINK REL="stylesheet" TYPE="text/css" HREF="../elements/calendar-win2k-2.css" TITLE="win2k-2">
 <SCRIPT TYPE="text/javascript" SRC="../elements/calendar_stripped.js"></SCRIPT>
 <SCRIPT TYPE="text/javascript" SRC="../elements/calendar-en.js"></SCRIPT>
@@ -113,6 +119,21 @@
 
 </TABLE><BR>
 
+%#so:
+%# - hide until you selecdt a pacakge with add-ons
+%# -lookup and display the available add-ons when 
+%# -add them to the (recur if there is one, otherwise setup) price and display magically like processing fees do on edit/cust_pay.cgi
+
+%# better label?
+<FONT CLASS = "fsinnerbox-title" 
+      ID    = "cust_pkg_usageprice_title"
+      STYLE = "display:none"
+><% mt('Usage add-ons') |h %></FONT>
+<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0 ID="cust_pkg_usageprice_table">
+
+</TABLE>
+<BR>
+
 % my $discount_cust_pkg = $curuser->access_right('Discount customer package');
 % my $waive_setup_fee   = $curuser->access_right('Waive setup fee');
 %
diff --git a/httemplate/misc/xmlhttp-part_pkg_usageprice.html b/httemplate/misc/xmlhttp-part_pkg_usageprice.html
new file mode 100644
index 0000000..d4e2d84
--- /dev/null
+++ b/httemplate/misc/xmlhttp-part_pkg_usageprice.html
@@ -0,0 +1,24 @@
+<% encode_json( \@return ) %>\
+<%init>
+
+my( $pkgpart ) = $cgi->param('arg');
+
+#could worry about agent-virting this so you can't see the add-on pricing of
+# other agents, but not a real-world big worry
+
+my $part_pkg = qsearchs( 'part_pkg', { pkgpart=>$pkgpart } );
+
+my $num = 0;
+
+my @return = map { 
+                   my @inc = ('/elements/cust_pkg_usageprice.html',
+                                'usagepricepart' => $_->usagepricepart,
+                             );
+
+                   ( include(@inc, field=>'usagepricenum'.$num, html_only=>1 ),
+                     include(@inc, field=>'usagepricenum'.$num++, js_only=>1 ),
+                   );
+                 }
+               $part_pkg->part_pkg_usageprice;
+
+</%init>

commit 49809d3653e7ac4951d36716dce3cd25ba9c3728
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue Jan 7 22:57:18 2014 -0800

    time/data/etc. unit pricing add-ons, RT#24392

diff --git a/FS/MANIFEST b/FS/MANIFEST
index bfc47c6..3bed3ee 100644
--- a/FS/MANIFEST
+++ b/FS/MANIFEST
@@ -743,3 +743,7 @@ FS/conferencing_type.pm
 t/conferencing_type.t
 FS/conferencing_quality.pm
 t/conferencing_quality.t
+FS/svc_video.pm
+t/svc_video.t
+FS/part_pkg_usageprice.pm
+t/part_pkg_usageprice.t
diff --git a/FS/t/part_pkg_usageprice.t b/FS/t/part_pkg_usageprice.t
new file mode 100644
index 0000000..8964839
--- /dev/null
+++ b/FS/t/part_pkg_usageprice.t
@@ -0,0 +1,5 @@
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::part_pkg_usageprice;
+$loaded=1;
+print "ok 1\n";

commit 4427ad71b12bf27eac2a05d88141a82f9372d03f
Author: Ivan Kohler <ivan at freeside.biz>
Date:   Tue Jan 7 22:55:58 2014 -0800

    time/data/etc. unit pricing add-ons, RT#24392

diff --git a/FS/FS/part_pkg_usageprice.pm b/FS/FS/part_pkg_usageprice.pm
index 0fa6bca..88e3870 100644
--- a/FS/FS/part_pkg_usageprice.pm
+++ b/FS/FS/part_pkg_usageprice.pm
@@ -2,6 +2,7 @@ package FS::part_pkg_usageprice;
 use base qw( FS::Record );
 
 use strict;
+use Tie::IxHash;
 #use FS::Record qw( qsearch qsearchs );
 
 =head1 NAME
@@ -120,6 +121,38 @@ sub check {
   $self->SUPER::check;
 }
 
+=item targets
+
+Returns a hash reference.  Keys are possible values for the "target" field.
+Values are hash references with "label" and "multiplier" keys.
+
+=cut
+
+sub targets {
+
+  tie my %targets, 'Tie::IxHash', # once?
+    #'svc_acct.totalbytes' => { label      => 'Megabytes',
+    #                           multiplier => 1048576,
+    #                         },
+    'svc_acct.totalbytes' => { label      => 'Gigabytes',
+                               multiplier => 1073741824,
+                             },
+    'svc_acct.seconds' => { label      => 'Hours',
+                            multiplier => 3600,
+                          },
+    'svc_conferencing.participants' => { label     => 'Conference Participants',
+                                         multiplier=> 1,
+                                       },
+  #this will take more work: set action, not increment..
+  #  and then value comes from a select, not a text field
+  #  'svc_conferencing.confqualitynum' => { label => 'Conference Quality',
+  #                                        },
+  ;
+
+  \%targets;
+
+}
+
 =back
 
 =head1 BUGS
diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi
index 8b50a50..b073866 100755
--- a/httemplate/browse/part_pkg.cgi
+++ b/httemplate/browse/part_pkg.cgi
@@ -277,6 +277,21 @@ push @fields, sub {
         : ()
       ),
     ],
+    (
+      map { my $amount = $_->amount
+              / (FS::part_pkg_usageprice->targets->{$_->target}{multiplier}||1);
+            my $label = FS::part_pkg_usageprice->targets->{$_->target}{label};
+            [
+              { data    => "Plus $money_char". $_->price. ' '.
+                           ( $_->action eq 'increment' ? 'per' : 'for' ).
+                           " $amount $label",
+                align   => 'center', #left?
+                colspan => 2,
+              },
+            ];
+          }
+        $part_pkg->part_pkg_usageprice
+    ),
     ( map { my $dst_pkg = $_->dst_pkg;
             [
               { data => 'Supplemental:  '.
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index 23de7c1..3fee36b 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -806,13 +806,15 @@ my $javascript = <<'END';
 
       var plan = what.options[what.selectedIndex].value;
 
-      var term_table = document.getElementById('TableNumber7') // XXX NOT ROBUST
+      var term_table = document.getElementById('TableNumber8') // XXX NOT ROBUST
       if ( plan == 'flat' || plan == 'prorate' || plan == 'subscription' ) {
         //term_table.disabled = false;
-        term_table.style.visibility = '';
+        //term_table.style.visibility = '';
+        term_table.style.display = '';
       } else {
         //term_table.disabled = true;
-        term_table.style.visibility = 'hidden';
+        //term_table.style.visibility = 'hidden';
+        term_table.style.display = 'none';
       }
 
       var currency_regex = /^(setup|recur)_fee_[A-Z]{3}$/;
diff --git a/httemplate/edit/process/part_pkg.cgi b/httemplate/edit/process/part_pkg.cgi
index 82c4e1e..69138bc 100755
--- a/httemplate/edit/process/part_pkg.cgi
+++ b/httemplate/edit/process/part_pkg.cgi
@@ -264,6 +264,21 @@ if ( $cgi->param('pkgpart') || ! $conf->exists('agent_defaultpkg') ) {
   };
 }
 
+my $targets = FS::part_pkg_usageprice->targets;
+foreach my $amount_param ( grep /^usagepricepart(\d+)_amount$/, $cgi->param ) {
+  $amount_param =~ /^usagepricepart(\d+)_amount$/ or die 'unpossible';
+  my $num = $1;
+  my $amount = $cgi->param($amount_param);
+  if ( ! $amount && ! $cgi->param("usagepricepart${num}_price") ) {
+    #don't add empty rows just because the dropdowns have a value
+    $cgi->param("usagepricepart${num}_$_", '') for qw( currency action target );
+    next;
+  } 
+  my $target = $cgi->param("usagepricepart${num}_target");
+  $amount *= $targets->{$target}{multiplier} if $targets->{$target}{multiplier};
+  $cgi->param($amount_param, $amount);
+}
+
 my @process_o2m = (
   {
     'table'  => 'part_pkg_msgcat',
@@ -272,6 +287,7 @@ my @process_o2m = (
   {
     'table'  => 'part_pkg_usageprice',
     'fields' => [qw( price currency action target amount )],
+
   }
 );
 
diff --git a/httemplate/elements/part_pkg_usageprice.html b/httemplate/elements/part_pkg_usageprice.html
index 5663469..5482137 100644
--- a/httemplate/elements/part_pkg_usageprice.html
+++ b/httemplate/elements/part_pkg_usageprice.html
@@ -64,24 +64,27 @@
                 ID   = "<%$id%>_target"
                 <% $onchange %>
         >
-%       foreach my $target (keys %targets) {
+%       foreach my $target (keys %$targets) {
           <OPTION VALUE="<% $target %>"
                   <% ($cgi->param($name.'_target') || $part_pkg_usageprice->target) eq $target ? 'SELECTED' : '' %>
-          ><% $targets{$target}->{label} %>
+          ><% $targets->{$target}->{label} %>
 %       }
       </TD>
 
 %     ###
 %     # amount
 %     ###
+%     my $amount =
+%       scalar($cgi->param($name.'_amount'))
+%         || ( $part_pkg_usageprice->amount
+%               / ($targets->{$part_pkg_usageprice->target}{multiplier} || 1) );
+%     $amount = '' unless $amount > 0;
       <TD>
         <INPUT TYPE = "text"
                NAME = "<%$name%>_amount"
                ID   = "<%$id%>_amount"
                SIZE = 5
-               VALUE = "<% scalar($cgi->param($name.'_amount'))
-                             || $part_pkg_usageprice->amount
-                        %>"
+               VALUE = "<% $amount %>"
                <% $onchange %>
         >
       </TD>
@@ -92,24 +95,7 @@
 % }
 <%init>
 
-tie my %targets, 'Tie::IxHash', # once?
-  #'svc_acct.totalbytes' => { label => 'Megabytes',
-  #                           mult  => 1048576,
-  #                         },
-  'svc_acct.totalbytes' => { label => 'Gigabytes',
-                             mult  => 1073741824,
-                           },
-  'svc_acct.seconds' => { label => 'Hours',
-                          mult  => 3600,
-                        },
-  'svc_conferencing.participants' => { label => 'Conference Participants',
-                                       mult  => 1,
-                                     },
-#this will take more work: set action, not increment..
-#  and then value comes from a select, not a text field
-#  'svc_conferencing.confqualitynum' => { label => 'Conference Quality',
-#                                        },
-;
+my $targets = FS::part_pkg_usageprice->targets;
 
 my( %opt ) = @_;
 

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

Summary of changes:
 FS/FS.pm                                           |    2 +
 FS/FS/Mason.pm                                     |    1 +
 FS/FS/Schema.pm                                    |   20 ++++++
 FS/FS/cust_pkg.pm                                  |   15 ++++
 .../{agent_currency.pm => cust_pkg_usageprice.pm}  |   45 +++++++-----
 FS/FS/part_pkg_usageprice.pm                       |   46 +++++++++++++
 FS/MANIFEST                                        |    6 ++
 FS/t/{AccessRight.t => cust_pkg_usageprice.t}      |    2 +-
 FS/t/{AccessRight.t => part_pkg_usageprice.t}      |    2 +-
 httemplate/browse/part_pkg.cgi                     |   14 ++++
 httemplate/edit/part_pkg.cgi                       |    8 ++-
 httemplate/edit/process/part_pkg.cgi               |   16 +++++
 httemplate/edit/process/quick-cust_pkg.cgi         |   15 ++++
 httemplate/elements/cust_pkg_usageprice.html       |   72 ++++++++++++++++++++
 httemplate/elements/order_pkg.js                   |   69 ++++++++++++++++++-
 httemplate/elements/order_pkg_link.html            |    2 +-
 httemplate/elements/part_pkg_usageprice.html       |   32 +++------
 ...usageprice.html => tr-cust_pkg_usageprice.html} |    2 +-
 httemplate/misc/detach_pkg.html                    |    2 -
 httemplate/misc/order_pkg.html                     |   21 ++++++
 httemplate/misc/xmlhttp-part_pkg_usageprice.html   |   24 +++++++
 21 files changed, 363 insertions(+), 53 deletions(-)
 copy FS/FS/{agent_currency.pm => cust_pkg_usageprice.pm} (59%)
 copy FS/t/{AccessRight.t => cust_pkg_usageprice.t} (77%)
 copy FS/t/{AccessRight.t => part_pkg_usageprice.t} (77%)
 create mode 100644 httemplate/elements/cust_pkg_usageprice.html
 copy httemplate/elements/{tr-part_pkg_usageprice.html => tr-cust_pkg_usageprice.html} (84%)
 create mode 100644 httemplate/misc/xmlhttp-part_pkg_usageprice.html




More information about the freeside-commits mailing list