diff options
Diffstat (limited to 'httemplate/edit/elements/ApplicationCommon.html')
-rw-r--r-- | httemplate/edit/elements/ApplicationCommon.html | 552 |
1 files changed, 552 insertions, 0 deletions
diff --git a/httemplate/edit/elements/ApplicationCommon.html b/httemplate/edit/elements/ApplicationCommon.html new file mode 100644 index 0000000..7b1050a --- /dev/null +++ b/httemplate/edit/elements/ApplicationCommon.html @@ -0,0 +1,552 @@ +<%doc> + +Examples: + + #cust_bill_pay + include('elements/ApplicationCommon.html', + 'form_action' => 'process/cust_bill_pay.cgi', + 'src_table' => 'cust_pay', + 'src_thing' => 'payment', + 'dst_table' => 'cust_bill', + 'dst_thing' => 'invoice', + ) + + #cust_credit_bill + include('elements/ApplicationCommon.html', + 'form_action' => 'process/cust_credit_bill.cgi', + 'src_table' => 'cust_credit', + 'src_thing' => 'credit', + 'dst_table' => 'cust_bill', + 'dst_thing' => 'invoice', + ) + + #cust_pay_refund + include('elements/ApplicationCommon.html', + 'form_action' => 'process/cust_pay_refund.cgi', + 'src_table' => 'cust_pay', + 'src_thing' => 'payment', + 'dst_table' => 'cust_refund', + 'dst_thing' => 'refund', + ) + + #cust_credit_refund + include('elements/ApplicationCommon.html', + 'form_action' => 'process/cust_credit_refund.cgi', + 'src_table' => 'cust_credit', + 'src_thing' => 'credit', + 'dst_table' => 'cust_refund', + 'dst_thing' => 'refund', + ) + +</%doc> + +<% include('/elements/header-popup.html', "Apply $src_thing$to", '', 'onLoad="myOnLoadFunction();"') %> + +<% include('/elements/error.html') %> + +<P ID="ErrorMessage"></P> +<FORM ACTION="<% $p1. $opt{'form_action'} %>" NAME="ApplicationForm" ID="ApplicationForm" METHOD=POST> + +<% $src_thing %> #<B><% $src_pkeyvalue %></B><BR> +<INPUT TYPE="hidden" NAME="<% $src_pkey %>" VALUE="<% $src_pkeyvalue %>"> + +<TABLE BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0> + +<TR> + <TD ALIGN="right">Date: </TD> + <TD><B><% time2str($date_format, $src->_date) %></B></TD> +</TR> + +<TR> + <TD ALIGN="right">Amount: </TD> + <TD ID="original_amount"><B><% $money_char %><% $src_amount %></B> + </TD> + <TD> +% if ($use_sub_dst_thing && $can_change_credit) { + <INPUT TYPE="hidden" NAME="src_amount" VALUE="<% $src_amount %>" > + <BUTTON TYPE="button" NAME="expand_button" ID="expand_button" onClick="do_change_amount(this);">Change</BUTTON> +% } + </TD> + +</TR> + +<TR> + <TD ALIGN="right">Unapplied amount: </TD> + <TD ID="unapplied_amount"><B><% $money_char %><% $unapplied %></B></TD> +</TR> + +% if ( $src_table eq 'cust_credit' ) { + <TR> + <TD ALIGN="right">Reason: </TD> + <TD COLSPAN=2><B><% $src->reason %></B></TD> + </TR> +% } + +</TABLE> +<BR> + +<SCRIPT TYPE="text/javascript"> +function clear_amounts() { + var rownum=0 + var table = document.getElementById('ApplicationTable'); + for (var row = 2; table.rows[row]; row++) + { + var inputs = table.rows[row].getElementsByTagName('input'); + if ( !inputs.length ) { + break; + } + inputs.item(0).value = ''; // amount + } + +} + +function changed(what) { + dst = what.options[what.selectedIndex].value; + + if ( dst == '' ) { + what.form.submit.disabled=true; +%if ($use_sub_dst_thing && $src_pkey eq 'crednum') { + what.form.tax_button.disabled=true; + what.form.clear_button.disabled=true; +%} + return true; + } + + what.form.submit.disabled=false; +%if ($use_sub_dst_thing && $src_pkey eq 'crednum') { + what.form.tax_button.disabled=false; + what.form.clear_button.disabled=false; +%} + +% foreach my $dst ( @dst ) { + + if ( dst == <% $dst->$dst_pkey %> ) { + what.form.amount.value = "<% min($dst->$dst_unapplied, $unapplied) %>"; +% if ($use_sub_dst_thing) { + what.form.display_amount.value = "<% min($dst->$dst_unapplied, $unapplied) %>"; + + var rownum=0 + var table = document.getElementById('ApplicationTable'); + while(table.rows[2]) { + table.deleteRow(2); + } +% my $app_class = "FS::$link_table"; +% my $temp_app = $app_class->new( +% { $src_pkey => $src_pkeyvalue, +% $dst_pkey => $dst->$dst_pkey, +% 'amount' => min($dst->$dst_unapplied, $unapplied), +% } +% ); +% my %apphash = (); +% my $listref_or_error = $temp_app->calculate_applications; +% %apphash = map { &{$key_generator}($_), $_ } @$listref_or_error +% if ref($listref_or_error); +% foreach my $cbp ( $dst->open_cust_bill_pkg ) { +% my $desc = $cbp->desc; +% my $total_owed = $cbp->owed_setup + $cbp->owed_recur; +% my $key = &{$key_generator}([ $cbp, 0, {} ]); +% my $amount = exists($apphash{ $key }) ? $apphash{ $key }->[1] : 0; +% unless ( $cbp->pkgnum ) { +% foreach my $taxX ( $cbp->cust_bill_pkg_tax_Xlocation ) { +% my $pkey = $taxX->primary_key; +% my $owed = $taxX->owed; +% my $key = &{$key_generator}([ $cbp, 0, { $pkey => $taxX->$pkey } ]); +% my $toapp = exists($apphash{ $key }) ? $apphash{ $key }->[1] : 0; + <% &{$row_generator}( $key, $cbp, $taxX->desc, $owed, $toapp, $taxX->$pkey ) %> +% $total_owed -= $owed; +% $amount -= $toapp; +% } +% $desc .= ' (default)'; +% } +% if ( $total_owed > 0 ) { + <% &{$row_generator}($key, $cbp, $desc, $total_owed, $amount, '') %> +% } +% } +% } + } + +% } + +} + +function sub_changed(what) { + + var amount = 0; + var table = document.getElementById('ApplicationTable'); + var i = table.rows.length; + while(i-- > 2) { + var inputs = table.rows[i].getElementsByTagName('input'); + if (! inputs.length) { + continue; + } + amount += parseFloat( inputs.item(0).value ) || 0; + } + what.form.amount.value = parseFloat(amount).toFixed(2); + what.form.display_amount.value = parseFloat(amount).toFixed(2); + set_amount_color(what); + +} + +function set_amount_color(what) { + if (what.form.src_amount.value < what.form.amount.value) { + what.form.display_amount.style.color = '#ff0000'; + } else { + what.form.display_amount.style.color = '#00ff00'; + } +} + +</SCRIPT> + +Apply to: + +% if ($use_sub_dst_thing && $src_pkey eq 'crednum') { +<CENTER> + <TABLE> + <TR> + <TD> + <BUTTON TYPE="button" NAME="tax_button" ID="tax_button" onClick="do_calculate_tax(this);" DISABLED>Calculate Tax</BUTTON> + </TD> + <TD> + <BUTTON TYPE="button" NAME="clear_button" ID="clear_button" onClick="clear_amounts(this);" DISABLED>Clear Amounts</BUTTON> + </TD> + </TR> + </TABLE> +</CENTER> +<% include( '/elements/xmlhttp.html', + 'url' => $p.'misc/xmlhttp-calculate_taxes.html', + 'subs' => [ 'calculate_taxes' ], + ) + %> +<SCRIPT TYPE="text/javascript"> + +function show_taxes(arg) { + var argsHash = eval('(' + arg + ')'); + + var button = document.getElementById('tax_button'); + button.disabled = false; + button.innerHTML = 'Calculate Tax'; + button = document.getElementById('clear_button'); + button.disabled = false; + + var error = argsHash['error']; + + var paragraph = document.getElementById('ErrorMessage'); + if (error) { + paragraph.innerHTML = 'Error: ' + error; + paragraph.style.color = '#ff0000'; + } else { + paragraph.innerHTML = ''; + } + var taxlines = argsHash['taxlines']; + + var table = document.getElementById('ApplicationTable'); + + var aFoundRow = 0; + for (i = 0; taxlines[i]; i++) { + var itemdesc = taxlines[i][0]; + var locnum = taxlines[i][2]; + if (taxlines[i][3]) { + locnum = taxlines[i][3]; + } + + var found = 0; + for (var row = 2; table.rows[row]; row++) { + var inputs = table.rows[row].getElementsByTagName('input'); + if (! inputs.length) { + while ( table.rows[row] ) { + table.deleteRow(row); + } + break; + } + if ( inputs.item(4).value == itemdesc && inputs.item(2).value == locnum ) + { + inputs.item(0).value = taxlines[i][1]; + aFoundRow = found = row; + break; + } + } + if (! found) { + var row = table.insertRow(table.rows.length); + var warning_cell = document.createElement('TD'); + warning_cell.style.color = '#ff0000'; + warning_cell.colSpan = 2; + warning_cell.innerHTML = 'Calculated Tax - ' + itemdesc + ' - ' + + taxlines[i][1] + ' will not be applied'; + row.appendChild(warning_cell); + } + } + + if (aFoundRow) { + sub_changed(table.rows[aFoundRow].getElementsByTagName('input').item(0)); + } + +} + +function do_calculate_tax (what) { + what.innerHTML = 'Calculating....'; + what.disabled = true; + var button = document.getElementById('clear_button'); + button.disabled = true; + var taxed_items = new Array(); + var table = document.getElementById('ApplicationTable'); + for (var row = 2; table.rows[row]; row++) + { + var inputs = table.rows[row].getElementsByTagName('input'); + if ( !inputs.length ) { + break; + } + var taxed_item = new Array( + inputs.item(1).value, // billpkgnum + inputs.item(3).value, // s_or_r + inputs.item(0).value || 0 // amount + ); + taxed_items.push(taxed_item); + } + + var args = new Array( + 'crednum', '<% $src_pkeyvalue %>', + 'items', taxed_items + ); + calculate_taxes ( args, show_taxes ); +} + +function do_change_amount (what) { + var amount_cell = document.getElementById('original_amount'); + var inputs = amount_cell.getElementsByTagName('input'); + if (inputs.length) { + src_amount_changed(); + amount_cell.innerHTML = '<B><% $money_char %></B>' + inputs.item(0).value; + } else { + amount_cell.innerHTML = '<% $money_char %>'; + var amount_input = document.createElement('INPUT'); + amount_input.setAttribute('name', 'entered_amount'); + amount_input.setAttribute('id', 'entered_amount'); + amount_input.style.textAlign = 'right'; + amount_input.setAttribute('size', 8); + amount_input.setAttribute('maxlength', 8); + amount_input.setAttribute('value', what.form.src_amount.value); + amount_input.setAttribute('onChange', "src_amount_changed(this);"); + amount_cell.appendChild(amount_input); + } +} + +function src_amount_changed () { + //alert('src_amount_changed called'); + var entered_amount = document.getElementById('entered_amount'); + if ( entered_amount ) { + entered_amount.form.src_amount.value = entered_amount.value; + var unapplied_cell = document.getElementById('unapplied_amount'); + unapplied_cell.innerHTML = '<B><% $money_char %>' + entered_amount.value + '</B>'; + set_amount_color(entered_amount); + } + return true; +} + +</SCRIPT> + +%} + +<TABLE ID="ApplicationTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0> + +<TR> + <TD ALIGN="right"><% $dst_thing %>: </TD> + <TD><SELECT NAME="<% $dst_pkey %>" SIZE=1 onChange="changed(this)"> +<OPTION VALUE="">Select <% $dst_thing %> + +% foreach my $dst ( @dst ) { + <OPTION<% $dst->$dst_pkey eq $dst_pkeyvalue ? ' SELECTED' : '' %> VALUE="<% $dst->$dst_pkey %>">#<% $dst->$dst_pkey %> - <% time2str($date_format, $dst->_date) %> - $<% $dst->$dst_unapplied %> +% } + +</SELECT> + </TD> +</TR> + +<TR> + <TD ALIGN="right">Amount: </TD> + <TD><% $money_char %><INPUT TYPE="text" NAME="<% $use_sub_dst_thing ? 'display_' : '' %>amount" VALUE="<% $amount %>" SIZE=8 MAXLENGTH=8 <% $use_sub_dst_thing ? 'DISABLED' : '' %> STYLE="text-align:right;"></TD> +% if ($use_sub_dst_thing) { + <INPUT TYPE="hidden" NAME="amount" VALUE="<% $amount %>" > +% } +</TR> + +</TABLE> + +<BR> +<CENTER><INPUT TYPE="submit" + VALUE="Apply" + NAME="submit" + ID="submit" +% if ($use_sub_dst_thing && $can_change_credit) { + onClick="src_amount_changed()" +% } + DISABLED +></CENTER> + +</FORM> + +<SCRIPT TYPE="text/javascript"> + +function myOnLoadFunction () { + <% $onload %> +} + +</SCRIPT> + +<% include('/elements/footer.html') %> + +<%init> + +my %opt = @_; + +my $conf = new FS::Conf; +my $money_char = $conf->config('money_char') || '$'; +my $date_format = $conf->config('date_format') || '%m/%d/%Y'; + +my $src_thing = ucfirst($opt{'src_thing'}); +my $src_table = $opt{'src_table'}; +my $src_pkey = dbdef->table($src_table)->primary_key; + +my $dst_thing = ucfirst($opt{'dst_thing'}); +my $dst_table = $opt{'dst_table'}; +my $dst_pkey = dbdef->table($dst_table)->primary_key; +my $dst_unapplied = $dst_table eq 'cust_bill' ? 'owed' : 'unapplied'; + +$opt{form_action} =~ /^process\/(.*)\./ or die "bad form action"; +my $link_table = $1; + +my $use_sub_dst_thing = 0; +$use_sub_dst_thing = 1 + if ( $dst_table eq 'cust_bill' && $conf->exists("${link_table}_pkg-manual") ); + +my $can_change_credit = 0; +$can_change_credit = 1 + if ( $src_table eq 'cust_credit' && + $FS::CurrentUser::CurrentUser->access_right('Post credit') && + $FS::CurrentUser::CurrentUser->access_right('Delete credit') + ); + +my $to = $dst_table eq 'cust_refund' ? ' to Refund' : ''; + +my($src_pkeyvalue, $amount, $dst_pkeyvalue, $src_amount); +if ( $cgi->param('error') ) { + $src_pkeyvalue = $cgi->param($src_pkey); + $amount = $cgi->param('amount'); + $dst_pkeyvalue = $cgi->param($dst_pkey); + $src_amount = $cgi->param('src_amount'); +} else { + my($query) = $cgi->keywords; + $query =~ /^(\d+)$/; + $src_pkeyvalue = $1; + $amount = ''; + $dst_pkeyvalue = ''; +} + +my $otaker = getotaker; + +my $p1 = popurl(1); + +my $src = qsearchs($src_table, { $src_pkey => $src_pkeyvalue } ); +die "$src_thing $src_pkeyvalue not found!" unless $src; + +$src_amount = $src->amount unless $cgi->param('error'); + +my $unapplied = $src->unapplied; + +my @dst = sort { $a->_date <=> $b->_date + or $a->$dst_pkey <=> $b->$dst_pkey + } + grep { $_->$dst_unapplied != 0 } + qsearch($dst_table, { 'custnum' => $src->custnum } ); + +my $row_generator = sub { + my ($key, $cust_bill_pkg, $desc, $owed, $amount, $taxXnum) = @_; + my ($num, $s_or_r, $taxlinenum) = split(':', $key); + my $id = $cust_bill_pkg->pkgnum || 'Tax'; + my $billpkgnum = $cust_bill_pkg->billpkgnum; + my $s_or_r = $cust_bill_pkg->setup > 0 ? 'setup' : 'recur'; + + $amount = sprintf("%.2f", $amount); + qq! + var tablebody = document.getElementsByTagName('tbody').item(0); + var row = table.insertRow(rownum+2); + var pkg_cell = document.createElement('TD'); + pkg_cell.style.textAlign = 'right'; + pkg_cell.innerHTML = "$id - $desc - $owed:"; + var amount_cell = document.createElement('TD'); + amount_cell.innerHTML = "$money_char"; + var amount_input = document.createElement('INPUT'); + amount_input.setAttribute('name', 'subamount'+rownum); + amount_input.setAttribute('id', 'subamount'+rownum); + amount_input.style.textAlign = 'right'; + amount_input.setAttribute('size', 8); + amount_input.setAttribute('maxlength', 8); + amount_input.setAttribute('rownum', rownum); + amount_input.setAttribute('value', "$amount"); + amount_input.setAttribute('onChange', "sub_changed(this);"); + amount_cell.appendChild(amount_input); + var subnum_input = document.createElement('INPUT'); + subnum_input.setAttribute('name', 'subnum'+rownum); + subnum_input.setAttribute('id', 'subnum'+rownum); + subnum_input.setAttribute('type', 'hidden'); + subnum_input.setAttribute('rownum', rownum); + subnum_input.setAttribute('value', "$billpkgnum"); + amount_cell.appendChild(subnum_input); + var taxnum_input = document.createElement('INPUT'); + taxnum_input.setAttribute('name', 'taxXlocationnum'+rownum); + taxnum_input.setAttribute('id', 'taxXlocationnum'+rownum); + taxnum_input.setAttribute('type', 'hidden'); + taxnum_input.setAttribute('rownum', rownum); + taxnum_input.setAttribute('value', "$taxXnum"); + amount_cell.appendChild(taxnum_input); + var s_or_r_input = document.createElement('INPUT'); + s_or_r_input.setAttribute('name', 's_or_r'+rownum); + s_or_r_input.setAttribute('id', 's_or_r'+rownum); + s_or_r_input.setAttribute('type', 'hidden'); + s_or_r_input.setAttribute('rownum', rownum); + s_or_r_input.setAttribute('value', "$s_or_r"); + amount_cell.appendChild(s_or_r_input); + var itemdesc_input = document.createElement('INPUT'); + itemdesc_input.setAttribute('name', 'itemdesc'+rownum); + itemdesc_input.setAttribute('id', 'itemdesc'+rownum); + itemdesc_input.setAttribute('type', 'hidden'); + itemdesc_input.setAttribute('rownum', rownum); + itemdesc_input.setAttribute('value', "$desc"); + amount_cell.appendChild(itemdesc_input); + row.appendChild(pkg_cell); + row.appendChild(amount_cell); + rownum++; + !; +}; + +my $key_generator = sub { + my $listref = shift; + my ($cust_bill_pkg, $amount, $hashref) = @$listref; + my $setup_or_recur = $cust_bill_pkg->setup > 0 ? 'setup' : 'recur'; + my $taxlinenum = $hashref->{billpkgtaxlocationnum} || + $hashref->{billpkgtaxratelocationnum} || + ''; + + join(':', $cust_bill_pkg->billpkgnum, $setup_or_recur, $taxlinenum); +}; + +my $onload = 'return true;'; + +if ($cgi->param('error')) { + + my $set_sub_amounts = + join(';', map { "myform.subamount$_.value = ". $cgi->param("subamount$_") } + grep { /.+/ } + map { /^subnum(\d+)$/ ? $1 : '' } + $cgi->param + ); + $set_sub_amounts &&= "$set_sub_amounts;sub_changed(myform.subamount0)"; + + $onload = qq! + var myform = document.getElementById('ApplicationForm'); + changed(myform.elements['$dst_pkey']); + $set_sub_amounts; + return true; + !; +} + +</%init> |