From 1115b9089e9d9ecf104bc61bb22e84f5233aa44b Mon Sep 17 00:00:00 2001 From: Jonathan Prykop Date: Tue, 9 Jun 2015 16:23:58 -0500 Subject: [PATCH] RT#33484: Delete lines from quick payment entry --- httemplate/elements/customer-table.html | 536 ++++++++++++++--------------- httemplate/misc/batch-cust_pay.html | 71 ++-- httemplate/misc/process/batch-cust_pay.cgi | 6 +- 3 files changed, 302 insertions(+), 311 deletions(-) diff --git a/httemplate/elements/customer-table.html b/httemplate/elements/customer-table.html index 83abad010..090623ff9 100644 --- a/httemplate/elements/customer-table.html +++ b/httemplate/elements/customer-table.html @@ -128,8 +128,8 @@ Example: return; } - if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) { - <% $opt{prefix} %>addRow(); + if ( document.getElementById('row'+searchrow).emptyrow ) { + <% $opt{prefix} %>newEmptyRow(searchrow); } var customer = document.getElementById('customer'+searchrow); customer.value = 'searching...'; @@ -179,8 +179,8 @@ Example: return; } - if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) { - <% $opt{prefix} %>addRow(); + if ( document.getElementById('row'+searchrow).emptyrow ) { + <% $opt{prefix} %>newEmptyRow(searchrow); } var customer_obj = document.getElementById('customer'+searchrow); @@ -262,8 +262,8 @@ Example: return; } - if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) { - <% $opt{prefix} %>addRow(); + if ( document.getElementById('row'+searchrow).emptyrow ) { + <% $opt{prefix} %>newEmptyRow(searchrow); } var invnum = document.getElementById('invnum'+searchrow); @@ -385,253 +385,101 @@ Example: } function update_num_open(rownum, newval) { + document.getElementById('num_open'+rownum).value = newval; num_open_invoices[rownum] = newval; } + function <% $opt{prefix} %>updateTotalRow () { + if ( <% $opt{prefix} %>totalrows == 1 ) { + <% $opt{prefix} %>total_el.innerHTML = + 'Total ' + + <% $opt{prefix} %>totalrows + + ' <% $opt{name_singular} || 'customer' %>'; + } else { + <% $opt{prefix} %>total_el.innerHTML = + 'Total ' + + <% $opt{prefix} %>totalrows + + ' <% PL($opt{name_singular} || 'customer') %>'; + } + } - + var <% $opt{prefix} %>total_el, <% $opt{prefix} %>rownum, <% $opt{prefix} %>totalrows, <% $opt{prefix} %>allrows; + + function <% $opt{prefix} %>addDeleteButton (searchrow) { + var td_delete = document.getElementById('delete'+searchrow); + var button_delete = document.createElement('INPUT'); + button_delete.setAttribute('rownum', searchrow); + button_delete.setAttribute('type', 'button'); + button_delete.setAttribute('value', 'X'); + button_delete.onclick = <% $opt{prefix} %>deleteRow; + button_delete.style.color = '#ff0000'; + button_delete.style.fontWeight = 'bold'; + button_delete.style.paddingLeft = '2px'; + button_delete.style.paddingRight = '2px'; + td_delete.appendChild(button_delete); + } - + function <% $opt{prefix} %>newEmptyRow (searchrow) { + // add delete button to current row + <% $opt{prefix} %>addDeleteButton(searchrow); + // mark current row as non-empty + var oldemptyrow = document.getElementById('row'+searchrow); + oldemptyrow.emptyrow = false; + // update totalrows + <% $opt{prefix} %>totalrows++ + <% $opt{prefix} %>updateTotalRow(); + // add a new empty row + <% $opt{prefix} %>addRow(); + } - - - - - - -% foreach my $header ( @{$opt{header}} ) { - + function <% $opt{prefix} %>deleteRow() { + var thisrownum = this.getAttribute('rownum'); +% if ( $opt{delete_row_callback} ) { + // callback + <% $opt{delete_row_callback} %>(thisrownum,'<% $opt{prefix} %>'); % } - -% my $row = 0; -% for ( $row = 0; exists($param->{"custnum$row"}); $row++ ) { - - - - - - - - - - - - -% my $col = 0; -% foreach my $field ( @{$opt{fields}} ) { -% my $value; -% if ( ref($field) eq 'CODE' ) { -% $value = &{$field}($row,$param); -% } else { -% $value = $param->{"$field$row"}; -% } -% my $name = (ref($field) eq 'CODE') ? "column${col}_$row" : "$field$row"; -% my $align = $align{ $opt{align}->[$col] || 'l' }; -% my $size = $sizes->[$col] || 10; -% my $color = $opt{color}->[$col]; -% my $font = $color ? qq() : ''; -% my $onchange = ''; -% if ( $opt{onchange}->[$col] ) { -% $onchange = 'onchange="'.$opt{onchange}->[$col].'"'; -% } -% elsif ( $opt{footer}->[$col] eq '_TOTAL' ) { -% $total[$col] += $value; -% $onchange = $opt{prefix}. "calc_total$col();"; -% $onchange = qq(onchange="$onchange" onkeyup="$onchange"); -% } - -% $col++; -% } - -% } - - - -% my $col = 0; -% foreach my $footer ( @{$opt{footer}} ) { -% my $align = $align{ $opt{'footer_align'}->[$col] || 'c' }; -% if ($footer eq '_TOTAL' ) { -% my $id = $opt{'fields'}->[$col]; -% $id = ref($id) ? "column${col}_TOTAL" : "${id}_TOTAL"; - -% } else { - -% } -% $col++; -% } - - -
Inv #Cust #StatusCustomerBalance<% $header %>
- " - rownum = "<% $row %>" - > - - - " - rownum = "<% $row %>" - > - " - rownum = "<% $row %>" - > - - - " - - ><% $param->{"status$row"} %> - " - rownum = "<% $row %>" - > - " - rownum = "<% $row %>" - > - - " rownum="<% $row %>"> - - - - - <% $money_char %> - <% $param->{"balance$row"} %> -   - " - rownum = "<% $row %>" - > - -% my $type = $types->[$col] || 'text'; -% if ($type eq 'text' or $type eq 'checkbox') { - - > -% } elsif ($types->[$col] eq 'immutable') { - <% $font %><% $value %><% $font ? '' : '' %> - -% } else { - Cannot represent unknown type: <% $types->[$col] %> -% } -
- Total <% $row ? $row-1 : 0 %> - <% PL($opt{name_singular} || 'customer', ( $row ? $row-1 : 0 ) ) %> -  <% sprintf('%.2f', $total[$col] ) %><% $footer %>
- - - -<% include('/elements/xmlhttp.html', - 'url' => $p. 'misc/xmlhttp-cust_main-search.cgi', - 'subs' => [qw( custnum_search smart_search invnum_search )], - ) -%> - - + + + + + + + + + +% foreach my $header ( @{$opt{header}} ) { + +% } + + +% my @rownums = sort { $a <=> $b } map /^custnum(\d+)$/, keys %$param; + + +% my $col = 0; +% foreach my $footer ( @{$opt{footer}} ) { +% my $align = $align{ $opt{'footer_align'}->[$col] || 'c' }; +% if ($footer eq '_TOTAL' ) { +% my $id = $opt{'fields'}->[$col]; +% $id = ref($id) ? "column${col}_TOTAL" : "${id}_TOTAL"; + +% } else { + +% } +% $col++; +% } + + +
Inv #Cust #StatusCustomerBalance<% $header %>
+ Total <% @rownums || 0 %> + <% PL($opt{name_singular} || 'customer', ( @rownums || 0 ) ) %> +  <% sprintf('%.2f', $total[$col] ) %><% $footer %>
+ + +<% include('/elements/xmlhttp.html', + 'url' => $p. 'misc/xmlhttp-cust_main-search.cgi', + 'subs' => [qw( custnum_search smart_search invnum_search )], + ) +%> + <%init> my(%opt) = @_; my $conf = new FS::Conf; +## caution when using prefix, it isn't consistently applied to tag id/name $opt{prefix} = '' unless defined $opt{prefix}; $opt{prefix} .= '_' if $opt{prefix}; diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index cc1a26a0e..fb3ec04f3 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -26,8 +26,27 @@ function warnUnload() { } window.onbeforeunload = warnUnload; -function add_row_callback(rownum, prefix) { - document.getElementById('enable_app'+rownum).disabled = true; +function add_row_callback(rownum, prefix, values) { + if (values) { + custnum_update_callback(rownum, prefix); + } else { + document.getElementById('enable_app'+rownum).disabled = true; + } +} + +function delete_row_callback(rownum, prefix) { + 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, prefix) { @@ -313,17 +332,17 @@ 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]; + for (appnum=0; appnum < row_obj[r].length; appnum++) { + this_app = row_obj[r][appnum]; var x = r + '.' + appnum; //set invnum var select_invnum = document.getElementById('invnum'+x); @@ -345,7 +364,7 @@ function preload() { } //for appnum }; //preload_row function toggle_application_row.call(enable, null, preload_row); - } // if row_array[rownum].length + } // if (row_obj[rownum].length } //for rownum } @@ -380,6 +399,7 @@ function preload() { custnum_update_callback => 'custnum_update_callback', invnum_update_callback => 'invnum_update_callback', add_row_callback => 'add_row_callback', + delete_row_callback => 'delete_row_callback', &>
@@ -387,13 +407,12 @@ function preload() { -%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') %> @@ -455,29 +474,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 }; diff --git a/httemplate/misc/process/batch-cust_pay.cgi b/httemplate/misc/process/batch-cust_pay.cgi index 1105af943..bb4b9733c 100644 --- a/httemplate/misc/process/batch-cust_pay.cgi +++ b/httemplate/misc/process/batch-cust_pay.cgi @@ -12,7 +12,8 @@ my $paybatch = time2str('webbatch-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time); my @cust_pay = (); #my $row = 0; #while ( exists($param->{"custnum$row"}) ) { -for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { +my @invrows = grep(/^invnum\d+\.\d+$/, keys %$param); +foreach my $row ( map /^custnum(\d+)$/, keys %$param ) { my $custnum = $param->{"custnum$row"}; my $cust_main; if ( $custnum =~ /^(\d+)$/ and $1 <= 2147483647 ) { @@ -48,7 +49,8 @@ for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { # payment applications, if any my @cust_bill_pay = (); - for ( my $app = 0; exists($param->{"invnum$row.$app"}); $app++ ) { + foreach my $app ( sort {$a <=> $b} map /^invnum$row\.(\d+)$/, @invrows ) { +# for ( my $app = 0; exists($param->{"invnum$row.$app"}); $app++ ) { next if !$param->{"invnum$row.$app"}; push @cust_bill_pay, new FS::cust_bill_pay { 'invnum' => $param->{"invnum$row.$app"}, -- 2.11.0