diff options
author | Jonathan Prykop <jonathan@freeside.biz> | 2015-09-10 21:33:37 -0500 |
---|---|---|
committer | Jonathan Prykop <jonathan@freeside.biz> | 2015-09-14 23:05:54 -0500 |
commit | 205cf3b843285a5858f1d6387386381564a5deca (patch) | |
tree | 2bf54867b4a4105c610147d3f28cfab99b0d3a31 /httemplate | |
parent | b78bb7aeaa27daab707106217b33e4096e985262 (diff) |
RT#33410: Package GB add-ons
Diffstat (limited to 'httemplate')
-rw-r--r-- | httemplate/edit/process/change-cust_pkg.html | 39 | ||||
-rw-r--r-- | httemplate/elements/cust_pkg_usageprice.html | 9 | ||||
-rw-r--r-- | httemplate/elements/order_pkg.js | 68 | ||||
-rwxr-xr-x | httemplate/misc/change_pkg.cgi | 23 | ||||
-rw-r--r-- | httemplate/misc/cust_pkg_usageprice.html | 121 | ||||
-rw-r--r-- | httemplate/misc/order_pkg.html | 21 | ||||
-rw-r--r-- | httemplate/misc/xmlhttp-part_pkg_usageprice.html | 18 |
7 files changed, 199 insertions, 100 deletions
diff --git a/httemplate/edit/process/change-cust_pkg.html b/httemplate/edit/process/change-cust_pkg.html index 046a9795c..308ea8ffd 100644 --- a/httemplate/edit/process/change-cust_pkg.html +++ b/httemplate/edit/process/change-cust_pkg.html @@ -59,6 +59,40 @@ unless ($error) { $error = $cust_pkg->change_later(\%change); } } else { + + # for now, can't change usageprice with change_later + my @old_cust_pkg_usageprice = $cust_pkg->cust_pkg_usageprice; + + # build new usageprice array + # false laziness with /edit/process/quick-cust_pkg.cgi + 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)), + }; + } + + # Need to figure out if usagepricepart quantities changed + my %oldup = map { $_->usagepricepart, $_->quantity } @old_cust_pkg_usageprice; + my %newup = map { $_->usagepricepart, $_->quantity } @cust_pkg_usageprice; + my $usagechanged = 0; + foreach my $up (keys %oldup) { + last if $usagechanged; + $usagechanged = 1 unless $oldup{$up} == $newup{$up}; + } + foreach my $up (keys %newup) { + last if $usagechanged; + $usagechanged = 1 unless $oldup{$up} == $newup{$up}; + } + $change{'cust_pkg_usageprice'} = \@cust_pkg_usageprice; + # special case: if there's a package change scheduled, and it matches # the parameters the user requested this time, then change to the existing # future package. @@ -68,12 +102,13 @@ unless ($error) { $change_to->pkgpart == $change{'pkgpart'} and $change_to->locationnum == $change{'locationnum'} and $change_to->quantity == $change{'quantity'} and - $change_to->contract_end == $change{'contract_end'} + $change_to->contract_end == $change{'contract_end'} and + !$usagechanged ) { %change = ( 'cust_pkg' => $change_to ); } } - + # do a package change right now my $pkg_or_error = $cust_pkg->change( \%change ); $error = ref($pkg_or_error) ? '' : $pkg_or_error; diff --git a/httemplate/elements/cust_pkg_usageprice.html b/httemplate/elements/cust_pkg_usageprice.html index 729099320..74b7842be 100644 --- a/httemplate/elements/cust_pkg_usageprice.html +++ b/httemplate/elements/cust_pkg_usageprice.html @@ -23,15 +23,16 @@ > % my $info = $part_pkg_usageprice->target_info; % my $amount = $part_pkg_usageprice->amount / ($info->{multiplier}||1); - <OPTION VALUE="">Additional <% $info->{label} %> + <OPTION VALUE="">Additional <% $info->{label} %></OPTION> % for (1..100) { #100? arbitrary. - <OPTION VALUE="<% $_ %>"><% +% my $selected = ($opt{'curr_quantity'} == $_) ? ' SELECTED' : ''; + <OPTION VALUE="<% $_ %>"<% $selected %>><% $money_char. sprintf('%.2f', $_ * $part_pkg_usageprice->price ). ' '. 'for'. #( $part_pkg_usageprice->action eq 'increment' ? 'per' : 'for' ). ' '. ( $_ * $amount ). ' '. $info->{label} - %> + %></OPTION> % } </SELECT> </TD> @@ -42,8 +43,6 @@ % } <%init> -#my $targets = FS::part_pkg_usageprice->targets; - my( %opt ) = @_; my $conf = new FS::Conf; diff --git a/httemplate/elements/order_pkg.js b/httemplate/elements/order_pkg.js index 3586a54cb..a850d2193 100644 --- a/httemplate/elements/order_pkg.js +++ b/httemplate/elements/order_pkg.js @@ -1,10 +1,12 @@ function pkg_changed () { var form = document.OrderPkgForm; var discountnum = form.discountnum; + var opt = form.pkgpart.options[form.pkgpart.selectedIndex]; + + usageprice_pkg_changed( opt.value ); if ( form.pkgpart.selectedIndex > 0 ) { - var opt = form.pkgpart.options[form.pkgpart.selectedIndex]; var date_button = document.getElementById('start_date_button'); var date_button_disabled = document.getElementById('start_date_disabled'); var date_text = document.getElementById('start_date_text'); @@ -68,78 +70,14 @@ function pkg_changed () { } } - get_part_pkg_usageprice( opt.value, update_part_pkg_usageprice ); - } else { form.submitButton.disabled = true; if ( discountnum ) { form.discountnum.disabled = true; } discountnum_changed(form.discountnum); } -} - -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/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi index e74747e82..b562d24cd 100755 --- a/httemplate/misc/change_pkg.cgi +++ b/httemplate/misc/change_pkg.cgi @@ -19,13 +19,13 @@ <& /elements/tr-select-cust-part_pkg.html, 'pre_label' => emt('New'), - 'curr_value' => scalar($cgi->param('pkgpart')), + 'curr_value' => scalar($cgi->param('pkgpart')) || $cust_pkg->pkgpart, 'classnum' => $part_pkg->classnum, 'cust_main' => $cust_main, &> <& /elements/tr-input-pkg-quantity.html, - 'curr_value' => $cust_pkg->quantity + 'curr_value' => scalar($cgi->param('quantity')) || $cust_pkg->quantity &> % if ($use_contract_end) { @@ -39,6 +39,11 @@ </TABLE> <BR> +<% include('/misc/cust_pkg_usageprice.html', + 'pkgpart' => (scalar($cgi->param('pkgpart')) || $cust_pkg->pkgpart), + 'pkgnum' => ($cust_pkg->change_to_pkgnum || $pkgnum), + ) %> +<BR> <FONT CLASS="fsinnerbox-title"><% mt('Change') |h %></FONT> <% ntable('#cccccc') %> @@ -49,8 +54,16 @@ document.getElementById('start_date_text').disabled = !enable; document.getElementById('start_date_button').style.display = (enable ? '' : 'none'); - document.getElementById('start_date_button_disabled').style.display = - (enable ? 'none' : ''); + if (document.getElementById('start_date_button_disabled')) { // does this ever exist anymore? + document.getElementById('start_date_button_disabled').style.display = + (enable ? 'none' : ''); + } + if (enable) { + usageprice_disable(1); + } else { + var form = document.OrderPkgForm; + usageprice_disable(0,form.pkgpart.options[form.pkgpart.selectedIndex].value); + } } <&| /elements/onload.js &> delay_changed(); @@ -96,7 +109,7 @@ TYPE = "button" VALUE = "<% mt("Change package") |h %>" onClick = "this.disabled=true; standardize_new_location();" - <% scalar($cgi->param('pkgpart')) ? '' : 'DISABLED' %> + <% #scalar($cgi->param('pkgpart')) ? '' : 'DISABLED' %> > </FORM> diff --git a/httemplate/misc/cust_pkg_usageprice.html b/httemplate/misc/cust_pkg_usageprice.html new file mode 100644 index 000000000..f2e0f57e6 --- /dev/null +++ b/httemplate/misc/cust_pkg_usageprice.html @@ -0,0 +1,121 @@ +<%doc> +Sets up the xmlhttp, javascript and initial (empty) table for selecting cust_pkg_usageprice. +Available values are based on pkgpart, and can be updated when changing pkgpart +by passing the new pkgpart to the following javascript: + + usageprice_pkg_changed( pkgpart, pkgnum ) + +The pkgnum input is optional, and will be used to set initial selected values. + +If pkgpart is passed as an option to this element, will run usageprice_pkg_changed +once to initialize table; pkgnum can be passed as an option along with this. + +You can disable usageprice selection temporarily (remove the fields from the form) +with the javascript usageprice_disable(1), and restore it with usageprice_disable(0,pkgnum). +While disabled, calling usageprice_pkg_changed will have no effect. +</%doc> + +<& /elements/xmlhttp.html, + 'url' => $p.'misc/xmlhttp-part_pkg_usageprice.html', + 'subs' => [ 'get_part_pkg_usageprice' ], +&> + +<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> + +<SCRIPT> + +var usagepriceCache = {}; +var usagepriceDisabled = 0; + +function usageprice_disable (disabled, pkgpart) { + if (disabled) { + usageprice_pkg_changed(0); + usagepriceDisabled = 1; + } else { + usagepriceDisabled = 0; + usageprice_pkg_changed(pkgpart); + } +} + +// main function to invoke when pkgpart changes +function usageprice_pkg_changed (pkgpart, pkgnum) { + if (usagepriceDisabled) return; + clear_part_pkg_usageprice(); + + if (pkgpart) { + if (usagepriceCache[pkgpart]) { + update_part_pkg_usageprice(pkgpart); + } else { + get_part_pkg_usageprice( pkgpart || 0, pkgnum || 0, download_part_pkg_usageprice ); + } + } +} + +// removes table rows & hides table title +function clear_part_pkg_usageprice () { + var table = document.getElementById('cust_pkg_usageprice_table'); + for ( var r = table.rows.length - 1; r >= 0; r-- ) { + table.deleteRow(r); + } + document.getElementById('cust_pkg_usageprice_title').style.display = 'none'; +} + +// catches response from xmlhttp request, updates cache & calls update function +function download_part_pkg_usageprice (part_pkg_usageprice) { + var usagepriceArray = JSON.parse(part_pkg_usageprice); + var pkgpart = usagepriceArray[0]; + usagepriceCache[pkgpart] = usagepriceArray; + update_part_pkg_usageprice(pkgpart); +} + +// updates from cache +function update_part_pkg_usageprice (pkgpart) { + if (usagepriceDisabled) return; + clear_part_pkg_usageprice(); + + var usagepriceArray = usagepriceCache[pkgpart]; + var table = document.getElementById('cust_pkg_usageprice_table'); + + // add the new usage price rows + var rownum = 0; + for ( var s = 1; s < usagepriceArray.length; s=s+2 ) { + var html = usagepriceArray[s]; + var javascript = usagepriceArray[s+1]; + + var row = table.insertRow(rownum++); + + var widget_cell = document.createElement('TD'); + 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'; + } + +} + +% if ($opt{'pkgpart'}) { +<&| /elements/onload.js &> +usageprice_pkg_changed(<% $opt{'pkgpart'} %>, <% $opt{'pkgnum'} %>); +</&> +% } + +</SCRIPT> + +<%init> +my %opt = @_; +</%init> + + diff --git a/httemplate/misc/order_pkg.html b/httemplate/misc/order_pkg.html index 799165fe0..cb2bd4832 100644 --- a/httemplate/misc/order_pkg.html +++ b/httemplate/misc/order_pkg.html @@ -5,11 +5,6 @@ } &> -<& /elements/xmlhttp.html, - 'url' => $p.'misc/xmlhttp-part_pkg_usageprice.html', - 'subs' => [ 'get_part_pkg_usageprice' ], -&> - <& /elements/init_calendar.html &> <SCRIPT TYPE="text/javascript" SRC="../elements/order_pkg.js"></SCRIPT> @@ -121,19 +116,9 @@ </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> +<% include('/misc/cust_pkg_usageprice.html', + 'pkgpart' => $pkgpart + ) %> <BR> % my $discount_cust_pkg = $curuser->access_right('Discount customer package'); diff --git a/httemplate/misc/xmlhttp-part_pkg_usageprice.html b/httemplate/misc/xmlhttp-part_pkg_usageprice.html index d4e2d8469..9decdeff9 100644 --- a/httemplate/misc/xmlhttp-part_pkg_usageprice.html +++ b/httemplate/misc/xmlhttp-part_pkg_usageprice.html @@ -1,24 +1,32 @@ <% encode_json( \@return ) %>\ <%init> -my( $pkgpart ) = $cgi->param('arg'); +my( $pkgpart, $pkgnum ) = $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 %curr_quantity; +if ($pkgnum) { + my $cust_pkg = qsearchs( 'cust_pkg', { pkgnum=>$pkgnum } ); + %curr_quantity = map { $_->usagepricepart, $_->quantity } $cust_pkg->cust_pkg_usageprice; +} + my $num = 0; -my @return = map { +# probably don't need to be returning js_only anymore? +my @return = ($pkgpart, map { + my $usagepricepart = $_->usagepricepart; my @inc = ('/elements/cust_pkg_usageprice.html', - 'usagepricepart' => $_->usagepricepart, + 'usagepricepart' => $usagepricepart, ); - + push(@inc,'curr_quantity',($curr_quantity{$usagepricepart} || 0)); ( include(@inc, field=>'usagepricenum'.$num, html_only=>1 ), include(@inc, field=>'usagepricenum'.$num++, js_only=>1 ), ); } - $part_pkg->part_pkg_usageprice; + $part_pkg->part_pkg_usageprice); </%init> |