X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=httemplate%2Fmisc%2Fbatch-cust_pay.html;h=003dc86ac91b3fe933e4ce1734f79d01cbb170e5;hp=cc1a26a0ea8568e5ac3b10e134c366143b5b7862;hb=79c8be3bd0c5db42794b36bf5b5dd25addba67cb;hpb=601137d2d3d57841f50f4ab5393c2e521ada263a diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index cc1a26a0e..003dc86ac 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -26,11 +26,30 @@ function warnUnload() { } window.onbeforeunload = warnUnload; -function add_row_callback(rownum, prefix) { - document.getElementById('enable_app'+rownum).disabled = true; +function add_row_callback(rownum, values) { + if (values) { + custnum_update_callback(rownum); + } else { + document.getElementById('enable_app'+rownum).disabled = true; + } } -function custnum_update_callback(rownum, prefix) { +function delete_row_callback(rownum) { + var i = 0; + var delbutton = document.getElementById('delete'+rownum+'.'+i); + var delrows = []; + while (delbutton) { + delrows[i] = delbutton; + i++; + delbutton = document.getElementById('delete'+rownum+'.'+i); + } + delrows = delrows.reverse(); + for (i = 0; i < delrows.length; i++) { + delrows[i].onclick(); + } +} + +function custnum_update_callback(rownum) { var custnum = document.getElementById('custnum'+rownum).value; // if there is a custnum and more than one open invoice, enable // (and check) the box @@ -39,17 +58,17 @@ function custnum_update_callback(rownum, prefix) { enable_app_checkbox.disabled = show_applications; % if ( $use_discounts ) { - select_discount_term(rownum, prefix); + select_discount_term(rownum); % } } -function invnum_update_callback(rownum, prefix) { - custnum_update_callback(rownum, prefix); +function invnum_update_callback(rownum) { + custnum_update_callback(rownum); } -function select_discount_term(row, prefix) { - var custnum_obj = document.getElementById('custnum'+prefix+row); - var select_obj = document.getElementById('discount_term'+prefix+row); +function select_discount_term(row) { + var custnum_obj = document.getElementById('custnum'+row); + var select_obj = document.getElementById('discount_term'+row); var value = ''; if (select_obj.type == 'hidden') { @@ -82,6 +101,10 @@ function select_discount_term(row, prefix) { var invoices_for_row = new Object; +var preloading = 0; // the number of preloading threads currently running + +// callback from toggle_application_row: we've received a list of +// the customer's open invoices. store them. function update_invoices(rownum, invoices) { invoices_for_row[rownum] = new Object; // only called before create_application_row @@ -94,6 +117,12 @@ function toggle_application_row(ev, next) { if (!next) next = function(){}; //optional continuation var rownum = this.getAttribute('rownum'); if ( this.checked ) { + // the user has opted to apply the payment to specific invoices. + // - lock the customer + // - fetch the list of open invoices + // - create a row to select an invoice + // - then optionally call "next", with this as the invocant + // and the rownum as argument; we use this to preload rows. var custnum = document.getElementById('custnum'+rownum).value; if (!custnum) return; lock_payment_row(rownum, true); @@ -105,6 +134,9 @@ function toggle_application_row(ev, next) { } ); } else { + // the user has opted not to do that. + // - remove all application rows + // - unlock the customer var row = document.getElementById('row'+rownum); var table_rows = row.parentNode.rows; for (i = row.sectionRowIndex; i < table_rows.count; i++) { @@ -164,6 +196,16 @@ function amount_unapplied(rownum) { var change_app_amount; +// the user has chosen an invoice. the previously chosen invoice is still +// in curr_invoice +// - if there is a value there, put it back on the invoices_for_row list for +// this customer. +// - then _remove_ the newly chosen invoice from that list. +// - find the "owed" element for this application row and set its value to the +// amount owed on that invoice. +// - find the "amount" element for this application row and set its value to +// either "owed" or the remaining payment amount, whichever is less. +// - call change_app_amount() on that element. function choose_app_invnum() { var rownum = this.getAttribute('rownum'); var appnum = this.getAttribute('appnum'); @@ -191,8 +233,10 @@ function choose_app_invnum() { } } +// the invoice selector has gained focus. clear its list of options, and +// replace them with the list of open invoices (from invoices_for_row). +// if there's already a selected invoice, prepend that to the list. function focus_app_invnum() { -% # invoice numbers just display as invoice numbers var rownum = this.getAttribute('rownum'); var add_opt = function(obj, value, label) { var o = document.createElement('OPTION'); @@ -214,14 +258,15 @@ function focus_app_invnum() { } } +// an application amount has been changed. if there's any unapplied payment +// amount, and any remaining invoices_for_row, add a blank application row. +// (but don't do this while preloading; it will unconditionally add enough +// rows to show all the attempted applications) function change_app_amount() { var rownum = this.getAttribute('rownum'); var appnum = this.getAttribute('appnum'); -%# maybe some kind of warning if amount_unapplied < 0? -%# only spawn a new application row if there are open invoices left, -%# and this is the highest-numbered application row for the customer, -%# and the sum of the applied amounts is < the amount of the payment, - if ( Object.keys(invoices_for_row[rownum]).length > 0 + if ( preloading == 0 + && Object.keys(invoices_for_row[rownum]).length > 0 && !document.getElementById( 'row'+rownum+'.'+(parseInt(appnum) + 1) ) && amount_unapplied(rownum) > 0 ) { @@ -229,6 +274,9 @@ function change_app_amount() { } } +// we're creating a payment application row. +// create the following elements: , s, "Apply to invoice" caption, +// invnum selector, "owed" display, amount input box, delete button. function create_application_row(rownum, appnum) { var payment_row = document.getElementById('row'+rownum); var tr_app = document.createElement('TR'); @@ -240,7 +288,7 @@ function create_application_row(rownum, appnum) { td_invnum.setAttribute('colspan', 4); td_invnum.style.textAlign = 'right'; td_invnum.appendChild( - document.createTextNode('<% mt('Apply to Invoice ') %>') + document.createTextNode(<% mt('Apply to Invoice ') |js_string %>) ); var select_invnum = document.createElement('SELECT'); select_invnum.setAttribute('rownum', rownum); @@ -313,39 +361,55 @@ function create_application_row(rownum, appnum) { %# for error handling--ugly, but the alternative is translating the whole %# process of creating rows into Mason -var row_array = <% encode_json(\@rows) %>; +var row_obj = <% encode_json(\%rows) %>; function preload() { var rownum; var appnum; - for (rownum=0; rownum < row_array.length; rownum++) { - if ( row_array[rownum].length ) { + for (rownum in row_obj) { + if ( row_obj[rownum].length ) { var enable = document.getElementById('enable_app'+rownum); enable.checked = true; var preload_row = function(r) {//continuation from toggle_application_row - for (appnum=0; appnum < row_array[r].length; appnum++) { - this_app = row_array[r][appnum]; - var x = r + '.' + appnum; - //set invnum - var select_invnum = document.getElementById('invnum'+x); - focus_app_invnum.call(select_invnum); - for (i=0; i 'custnum_update_callback', invnum_update_callback => 'invnum_update_callback', add_row_callback => 'add_row_callback', + delete_row_callback => 'delete_row_callback', &>
- + -%if ( $cgi->param('error') ) { - -%} +% #XXX I think this can go away completely, but need to test with $use_discount +% ###not perl <% include('/elements/footer.html') %> @@ -405,18 +469,19 @@ die "access denied" my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; -my @header = ( 'Amount', 'Check #' ); -my @fields = ( 'paid', 'payinfo' ); -my @types = ( '', '' ); -my @align = ( 'r', 'r' ); -my @sizes = ( 8, 10 ); -my @colors = ( '', '' ); +my @header = ( 'Amount', 'Check #', 'Date override' ); +my @fields = ( 'paid', 'payinfo', '_date' ); +my @types = ( '', '', 'date', ); +my @align = ( 'r', 'r', 'r' ); +my @sizes = ( 8, 10, 8 ); +my @colors = ( '', '', '' ); my %param = (); -my @footer = ( '_TOTAL', '' ); -my @footer_align = ( 'r', 'r' ); -my @onchange = ( '', '' );; +my @footer = ( '_TOTAL', '', '' ); +my @footer_align = ( 'r', 'r', '' ); +my @onchange = ( '', '', '' ); my $use_discounts = ''; +# Not entirely sure this works anymore... if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM part_pkg_discount') ) { #push @header, 'Discount'; push @header, ''; @@ -441,6 +506,16 @@ push @footer, ''; push @footer_align, ''; push @onchange, 'toggle_application_row'; +push @header, 'No Auto Allocate'; +push @fields, 'no_auto_apply'; +push @types, 'checkbox'; +push @align, 'c'; +push @sizes, '0'; +push @colors, ''; +push @footer, ''; +push @footer_align, ''; +push @onchange, ''; + #push @header, 'Error'; push @header, ''; push @fields, 'error'; @@ -455,29 +530,31 @@ push @onchange, ''; $m->comp('/elements/handle_uri_query'); # set up for preloading -my @rows; -my @row_errors; +my %rows; +my %row_errors; if ( $cgi->param('error') ) { my $param = $cgi->Vars; my $enum = 0; #errors numbered separately - for( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { - $rows[$row] = []; - $row_errors[$row] = $param->{"error$enum"}; + my @invrows = grep /^invnum\d+\.\d+$/, keys %$param; #pare down possibilities + foreach my $row ( sort { $a <=> $b } map /^custnum(\d+)$/, keys %$param ) { +# for( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { + $rows{$row} = []; + $row_errors{$row} = $param->{"error$enum"}; $enum++; - for( my $app = 0; exists($param->{"invnum$row.$app"}); $app++ ) { + foreach my $app ( map /^invnum$row\.(\d+)$/, @invrows ) { next if !$param->{"invnum$row.$app"}; my %this_app = map { $_ => ($param->{$_.$row.'.'.$app} || '') } qw( invnum amount ); $this_app{'error'} = $param->{"error$enum"} || ''; $param->{"error$enum"} = ''; # don't pass this error through - $rows[$row][$app] = \%this_app; + $rows{$row}[$app] = \%this_app; $enum++; } } - for( my $row = 0; $row < @row_errors; $row++ ) { - $param->{"error$row"} = $row_errors[$row]; + foreach my $row (keys %rows) { + $param->{"error$row"} = $row_errors{$row}; } } -#warn Dumper {rows => \@rows, row_errors => \@row_errors }; +#warn Dumper {rows => \%rows, row_errors => \%row_errors };