quick payment tool improvements, RT10698
[freeside.git] / httemplate / elements / customer-table.html
index fc298b0..c3a5df9 100644 (file)
@@ -1,18 +1,55 @@
-%  # options example...  
-%  #
-%  # #listrefs...
-%  # 'header'      => [ '#', 'Item' ],
-%  # 'fields'      => [
-%  #                    'column',
-%  #                    sub { my ($row,$param) = @_; $param->{"column$row"}; },
-%  #                  ],
-%  # 'sizes'       => [],                         # sizes ignored for immutable
-%  # 'types'       => ['immutable', ''],          # immutable or ''/text
-%  # 'param'       => { column0 => 1 },           # preset column of row 0 to 1
-%  # 
+<%doc>
+
+Example:
+
+  include( '/elements/customer-table.html',
+
+             ###
+             # required
+             ###
+
+             #listrefs...
+             'header'        => [ '#', 'Item' ],
+             'fields'        => [
+                                  'column',
+                                  sub { my ($row,$param) = @_;
+                                        $param->{"column$row"};
+                                      },
+                                ],
+
+             ###
+             # optional
+             ###
+
+             'name_singular' => 'customer', #label
+             'custnum_update_callback' => 'name_of_js_callback' #passed a rownum
+
+             #listrefs
+             'types'         => ['immutable', ''], # immutable or ''/text
+             'align'         => [ 'c', 'l', 'r', '' ],
+             'size'          => [],                # sizes ignored for immutable
+             'color'         => [],
+             'footer'        => ['string', '_TOTAL'], # strings or the special
+                                                      #value _TOTAL
+             'footer_align'  => [ 'c', 'l', 'r', '' ],
+
+             'param'         => { column0 => 1 },  # preset column of row 0 to 1
+
+         )
+
+</%doc>
 
 <SCRIPT TYPE="text/javascript">
 
+  function clearhint_invnum() {
+
+    if ( this.value == 'Not found' || this.value == 'Multiple' ) {
+      this.value = '';
+      this.style.color = '#000000';
+    }
+
+  }
+
   function clearhint_custnum() {
 
     if ( this.value == 'Not found' || this.value == 'Multiple' ) {
       this.value = '';
 
   }
+  
+  function <% $opt{prefix} %>search_invnum() {
+
+    this.style.color = '#000000'
+
+    var invnum_obj = this;
+    var searchrow = this.getAttribute('rownum');
+    var invnum = this.value;
+
+    if ( invnum == 'searching...' || invnum == 'Not found' || invnum == '' )
+      return;
+
+    if ( this.getAttribute('magic') == 'nosearch' ) {
+      this.setAttribute('magic', '');
+      return;
+    }
+
+    if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) {
+      <% $opt{prefix} %>addRow();
+    }
+    var customer = document.getElementById('customer'+searchrow);
+    customer.value = 'searching...';
+    customer.disabled = true;
+    customer.style.color = '#000000';
+    customer.style.backgroundColor = '#dddddd';
+
+    var customer_select = document.getElementById('cust_select'+searchrow);
+
+    customer.style.display = '';
+    customer_select.style.display = 'none';
+    
+    var custnum_obj = document.getElementById('custnum'+searchrow);
+    var balance = document.getElementById('balance'+searchrow);
+    balance.value = '';
+
+    function search_invnum_update(customers) {
+      
+      var customerArray = eval('(' + customers + ')');
+
+      custnum_obj.disabled = false;
+      custnum_obj.style.backgroundColor = '#ffffff';
+      customer.disabled = false;
+      customer.style.backgroundColor = '#ffffff';
+
+      if ( customerArray.length == 0 ) {
+
+        custnum_obj.value = 'Not found';
+       customer.value = 'Not found';
+        custnum_obj.style.color = '#ff0000';
+        customer.style.color = '#ff0000';
+
+        customer.style.display = '';
+        customer_select.style.display = 'none';
+
+      } else if ( customerArray.length == 3 ) {
+
+        custnum_obj.value = customerArray[0];
+        custnum_obj.style.color = '#000000';
+        customer.value = customerArray[1];
+        balance.value = customerArray[2];
+
+        customer.style.display = '';
+        customer_select.style.display = 'none';
+
+% if ( $opt{invnum_update_callback} ) {
+        <% $opt{invnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
+% }
+
+      }
+
+    }
+
+    invnum_search( invnum, search_invnum_update );
+
+  }
+
 
   function <% $opt{prefix} %>search_custnum() {
 
     customer.style.display = '';
     customer_select.style.display = 'none';
 
+    var invnum = document.getElementById('invnum'+searchrow);
+    invnum.value = '';
+    
+    var balance = document.getElementById('balance'+searchrow);
+    balance.value = '';
+
     function search_custnum_update(name) {
 
       var name = eval('(' + name + ')' );
       if ( name.length > 0 ) {
         customer.value = name;
         customer.setAttribute('magic', 'nosearch');
+% if ( $opt{custnum_update_callback} ) {
+        <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
+% }
       } else {
         customer.value = 'Not found';
         customer.style.color = '#ff0000';
     if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) {
       <% $opt{prefix} %>addRow();
     }
+    
+    var invnum = document.getElementById('invnum'+searchrow);
+    invnum.value = '';
 
     var custnum_obj = document.getElementById('custnum'+searchrow);
     custnum_obj.value = 'searching...';
     custnum_obj.style.backgroundColor = '#dddddd';
 
     var customer_select = document.getElementById('cust_select'+searchrow);
+    
+    var balance = document.getElementById('balance'+searchrow);
+    balance.value = '';
 
     function search_customer_update(customers) {
 
         customer_obj.style.display = '';
         customer_select.style.display = 'none';
 
-
       } else if ( customerArray.length == 1 ) {
 
         custnum_obj.value = customerArray[0][0];
         customer_obj.value = customerArray[0][1];
+        balance.value = customerArray[0][2];
 
         customer_obj.style.display = '';
         customer_select.style.display = 'none';
 
+% if ( $opt{custnum_update_callback} ) {
+        <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
+% }
 
       } else {
 
       this.style.display = 'none';
       customer_obj.style.display = '';
 
+% if ( $opt{custnum_update_callback} ) {
+      <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
+% }
+
     }
 
   }
 <TABLE ID="<% $opt{prefix} %>OneTrueTable" BGCOLOR="#cccccc" BORDER=0 CELLSPACING=0>
 
 <TR>
+  <TH>Inv #</TH>
   <TH>Cust #</TH>
   <TH>Customer</TH>
 % foreach my $header ( @{$opt{header}} ) {
     <TH><% $header %></TH>
 % }
+  <TH>Balance</TH>
 </TR>
 % my $row = 0;
 % for ( $row = 0; exists($param->{"custnum$row"}); $row++ ) { 
 
     <TR>
+      <TD>
+       <INPUT TYPE      = "text"
+               NAME      = "invnum<% $row %>"
+               ID        = "invnum<% $row %>"
+               SIZE      = 8
+               MAXLENGTH = 12
+               STYLE     = "text-align:right;"
+               VALUE     = "<% $param->{"invnum$row"} %>"
+               rownum    = "<% $row %>"
+        >
+        <SCRIPT TYPE="text/javascript">
+          var invnum_input<% $row %> = document.getElementById("invnum<% $row %>");
+          invnum_input<% $row %>.onfocus = clearhint_invnum;
+          invnum_input<% $row %>.onchange = <% $opt{prefix} %>search_invnum;
+        </SCRIPT>
+      </TD>
 
       <TD>
-        <INPUT TYPE="text" NAME="custnum<% $row %>" ID="custnum<% $row %>" SIZE=8 MAXLENGTH=12 VALUE="<% $param->{"custnum$row"} %>" rownum="<% $row %>">
-          <SCRIPT TYPE="text/javascript">
-            var custnum_input<% $row %> = document.getElementById("custnum<% $row %>");
-            custnum_input<% $row %>.onfocus = clearhint_custnum;
-            custnum_input<% $row %>.onchange = <% $opt{prefix} %>search_custnum;
-          </SCRIPT>
+        <INPUT TYPE      = "text"
+               NAME      = "custnum<% $row %>"
+               ID        = "custnum<% $row %>"
+               SIZE      = 8
+               MAXLENGTH = 12
+               STYLE     = "text-align:right;"
+               VALUE     = "<% $param->{"custnum$row"} %>"
+               rownum    = "<% $row %>"
+        >
+        <SCRIPT TYPE="text/javascript">
+          var custnum_input<% $row %> = document.getElementById("custnum<% $row %>");
+          custnum_input<% $row %>.onfocus = clearhint_custnum;
+          custnum_input<% $row %>.onchange = <% $opt{prefix} %>search_custnum;
+        </SCRIPT>
       </TD>
 
       <TD>
 %     } else {
 %       $value = $param->{"$field$row"}; 
 %     }
-%     my $name = (ref($field) eq 'CODE') ? "column${col}_$row" : "$field$row";
-%     my $size = $sizes->[$col] || 10;
-      <TD>
+%     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(<FONT COLOR="$color">) : '';
+%     my $onchange = '';
+%     if ( $opt{footer}->[$col] eq '_TOTAL' ) {
+%       $total[$col] += $value;
+%       $onchange = $opt{prefix}. "calc_total$col();";
+%       $onchange = qq(onchange="$onchange" onkeyup="$onchange");
+%     }
+      <TD ALIGN="<% $align %>">
 %     if (! $types->[$col] || $types->[$col] eq 'text') {
-        <INPUT TYPE="text" NAME="<% $name %>" SIZE="<% $size %>" VALUE="<% $value %>" >
+        <INPUT TYPE  = "text"
+               NAME  = "<% $name %>"
+               ID    = "<% $name %>"
+               SIZE  = "<% $size %>"
+               STYLE = "text-align: <% $align %>;"
+               VALUE = "<% $value %>"
+               <% $onchange %>
+        >
 %     } elsif ($types->[$col] eq 'immutable') {
-        <% $value %>
-        <INPUT TYPE="hidden" NAME="<% $name %>" VALUE="<% $value %>" >
+        <% $font %><% $value %><% $font ? '</FONT>' : '' %>
+        <INPUT TYPE="hidden" ID="<% $name %>" NAME="<% $name %>" VALUE="<% $value %>" >
 %     } else {
         Cannot represent unknown type: <% $types->[$col] %>
 %     }
       </TD>
 %     $col++;
 %   }
-
+      <TD>
+       <INPUT TYPE      = "text"
+               NAME      = "balance<% $row %>"
+               ID        = "balance<% $row %>"
+               SIZE      = 8
+               MAXLENGTH = 12
+               STYLE     = "text-align:right;"
+               VALUE     = "<% $param->{"balance$row"} %>"
+               rownum    = "<% $row %>"
+        >
+      </TD>
     </TR>
 % } 
 
+<TR>
+  <TH COLSPAN=3 ID="<% $opt{'prefix'} %>_TOTAL_TOTAL">
+    Total <% $row ? $row-1 : 0 %>
+    <% PL($opt{name_singular} || 'customer', ( $row ? $row-1 : 0 ) ) %>
+  </TH>
+% 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";
+      <TH ALIGN="<% $align %>" ID="<% $id %>">&nbsp;<% sprintf('%.2f', $total[$col] ) %></TH>
+%   } else {
+      <TH ALIGN="<% $align %>"><% $footer %></TH>
+%   }
+%   $col++;
+% }
+</TR>
 
 </TABLE>
 
+<SCRIPT TYPE="text/javascript">
+% my $col = 0;
+% foreach my $footer ( @{$opt{footer}} ) {
+%   if ($footer eq '_TOTAL' ) {
+%     my $name = $opt{fields}->[$col];
+%     $name = ref($name) ? "column$col" : $name;
+      var <% $opt{prefix}.$name %>_CACHE = new Array ();
+      var <% $opt{prefix} %>th_el = document.getElementById("<%$name%>_TOTAL");
+      function <% $opt{prefix} %>calc_total<% $col %>() {
+        var row = 0;
+        var total = 0;
+        for ( var row = 0;
+              
+              ( <% $opt{prefix}.$name%>_CACHE[row] =
+                                        <% $opt{prefix}.$name%>_CACHE[row]
+                                     || document.getElementById("<%$name%>"+row)
+              ) != null;
+              
+              row++
+            )
+        {
+          var value = <%$name%>_CACHE[row].value;
+          value = parseFloat(value);
+          if ( ! isNaN(value) ) {
+            total = total + value;
+          }
+        }
+        <% $opt{prefix} %>th_el.innerHTML = '&nbsp;' + total.toFixed(2);
+
+      }
+%   }
+%   $col++;
+% }
+</SCRIPT>
+
 <% include('/elements/xmlhttp.html',
               'url'  => $p. 'misc/xmlhttp-cust_main-search.cgi',
-              'subs' => [qw( custnum_search smart_search )],
+              'subs' => [qw( custnum_search smart_search invnum_search )],
            )
 %>
 
 <SCRIPT TYPE="text/javascript">
 
+  var <% $opt{prefix} %>total_el =
+    document.getElementById("<% $opt{'prefix'} %>_TOTAL_TOTAL");
+
   var <% $opt{prefix} %>rownum = <% $row %>;
 
   function <% $opt{prefix} %>addRow() {
     var table = document.getElementById('<% $opt{prefix} %>OneTrueTable');
     var tablebody = table.getElementsByTagName('tbody').item(0);
 
-    var row = document.createElement('TR');
+    var row = table.insertRow(rownum+1);
+    
+    var invnum_cell = document.createElement('TD');
+
+      var invnum_input = document.createElement('INPUT');
+      invnum_input.setAttribute('name', 'invnum'+<% $opt{prefix} %>rownum);
+      invnum_input.setAttribute('id',   'invnum'+<% $opt{prefix} %>rownum);
+      invnum_input.style.textAlign = 'right';
+      invnum_input.setAttribute('size', 8);
+      invnum_input.setAttribute('maxlength', 12);
+      invnum_input.setAttribute('rownum', <% $opt{prefix} %>rownum);
+      invnum_input.onfocus = clearhint_invnum;
+      invnum_input.onchange = <% $opt{prefix} %>search_invnum;
+      invnum_cell.appendChild(invnum_input);
+
+    row.appendChild(invnum_cell);
 
     var custnum_cell = document.createElement('TD');
 
       var custnum_input = document.createElement('INPUT');
       custnum_input.setAttribute('name', 'custnum'+<% $opt{prefix} %>rownum);
       custnum_input.setAttribute('id',   'custnum'+<% $opt{prefix} %>rownum);
+      custnum_input.style.textAlign = 'right';
       custnum_input.setAttribute('size', 8);
       custnum_input.setAttribute('maxlength', 12);
       custnum_input.setAttribute('rownum', <% $opt{prefix} %>rownum);
 
 %   my $col = 0;
 %   foreach my $field ( @{$opt{fields}} ) {
-    var my_cell = document.createElement('TD');
+
+      var my_cell = document.createElement('TD');
+      my_cell.setAttribute('align', '<% $align{ $opt{align}->[$col] || 'l' } %>');
 
 %     if ($types->[$col] eq 'immutable') {
 %       my $value;
 
       var my_input = document.createElement('INPUT');
       my_input.setAttribute('name', '<% $field %>'+<% $opt{prefix} %>rownum);
+      my_input.setAttribute('id',   '<% $field %>'+<% $opt{prefix} %>rownum);
+      my_input.style.textAlign = '<% $align{ $opt{align}->[$col] || 'l' } %>';
       my_input.setAttribute('size', <% $sizes->[$col] || 10 %>);
 %     if ($types->[$col] eq 'immutable') {
         my_input.setAttribute('type', 'hidden');
 %     }
+%     if ( $opt{footer}->[$col] eq '_TOTAL' ) {
+        my_input.onchange   = <% $opt{prefix} %>calc_total<%$col%>;
+        my_input.onkeyup    = <% $opt{prefix} %>calc_total<%$col%>;
+%     }
       my_cell.appendChild(my_input);
 
     row.appendChild(my_cell);
 %     $col++;
 %   }
 
-    tablebody.appendChild(row);
+    var balance_cell = document.createElement('TD');
+
+      var balance_input = document.createElement('INPUT');
+      balance_input.setAttribute('name', 'balance'+<% $opt{prefix} %>rownum);
+      balance_input.setAttribute('id',   'balance'+<% $opt{prefix} %>rownum);
+      balance_input.style.textAlign = 'right';
+      balance_input.setAttribute('size', 8);
+      balance_input.setAttribute('maxlength', 12);
+      balance_input.setAttribute('rownum', <% $opt{prefix} %>rownum);
+      balance_input.disabled = true;
+      balance_input.style.backgroundColor = '#dddddd';
+      balance_cell.appendChild(balance_input);
+
+    row.appendChild(balance_cell);
+
+    //update the total # of rows display
+    if ( <% $opt{prefix} %>rownum == 1 ) {
+      <% $opt{prefix} %>total_el.innerHTML =
+        'Total '
+          + <% $opt{prefix} %>rownum
+          + ' <% $opt{name_singular} || 'customer' %>';
+    } else {
+      <% $opt{prefix} %>total_el.innerHTML =
+        'Total '
+          + <% $opt{prefix} %>rownum
+          + ' <% PL($opt{name_singular} || 'customer') %>';
+    }
 
     <% $opt{prefix} %>rownum++;
 
@@ -379,9 +672,19 @@ $opt{prefix} = '' unless defined $opt{prefix};
 $opt{prefix} .= '_' if $opt{prefix};
 
 my $types = $opt{'types'} ? [ @{$opt{'types'}} ] : [];
-my $sizes = $opt{'sizes'} ? [ @{$opt{'sizes'}} ] : [];
+my $sizes = $opt{'size'} ? [ @{$opt{'size'}} ] : [];
 
 my $param = $opt{param};
 $param = $cgi->Vars if $cgi->param('error');
 
+$opt{$_} ||= [] foreach qw(align color footer footer_align);
+
+my @total = map 0, @{$opt{footer}};
+
+my %align = (
+  'l' => 'left',
+  'r' => 'right',
+  'c' => 'center',
+);
+
 </%init>