[freeside-commits] branch master updated. f4bb9273f1ba174858e221fd37f6dd1dca4119e9

Mark Wells mark at 420.am
Tue Sep 6 13:32:02 PDT 2016


The branch, master has been updated
       via  f4bb9273f1ba174858e221fd37f6dd1dca4119e9 (commit)
      from  c33b039c24de7192a72b172b317937f749c2cea3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit f4bb9273f1ba174858e221fd37f6dd1dca4119e9
Author: Mark Wells <mark at freeside.biz>
Date:   Tue Sep 6 12:42:34 2016 -0700

    UI improvements for selecting taxproducts, #71555 and #71556

diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi
index 1e8b510..acc3211 100755
--- a/httemplate/browse/part_pkg.cgi
+++ b/httemplate/browse/part_pkg.cgi
@@ -27,6 +27,19 @@
                  'html_foot'             => $html_foot,
              )
 %>
+<%def .style>
+<STYLE TYPE="text/css">
+  .taxproduct_desc {
+    color: blue;
+    text-decoration: underline dotted;
+  }
+</STYLE>
+<SCRIPT TYPE="text/javascript">
+$().ready(function() {
+  $('.taxproduct_desc').tooltip({});
+});
+</SCRIPT>
+</%def>
 <%init>
 
 my $curuser = $FS::CurrentUser::CurrentUser;
@@ -45,6 +58,7 @@ die "access denied"
 
 my $conf = new FS::Conf;
 my $taxclasses = $conf->exists('enable_taxclasses');
+my $taxvendor = $conf->config('tax_data_vendor');
 my $money_char = $conf->config('money_char') || '$';
 
 my $select = '*';
@@ -180,6 +194,7 @@ my $html_init = qq!
     </FORM>
     <BR><BR>
   !;
+$html_init .= include('.style');
 
 $cgi->param('dummy', 1);
 
@@ -562,6 +577,43 @@ if ( $taxclasses ) {
   push @header, 'Taxclass';
   push @fields, sub { shift->taxclass() || ' '; };
   $align .= 'l';
+} elsif ( $taxvendor ) {
+  push @header, 'Tax product';
+  my @classnums = ( 'setup', 'recur' );
+  my @classnames = ( 'Setup', 'Recur' );
+  foreach ( qsearch('usage_class', { disabled => '' }) ) {
+    push @classnums, $_->classnum;
+    push @classnames, $_->classname;
+  }
+  my $taxproduct_sub = sub {
+    my $ppt = shift;
+    '<SPAN CLASS="taxproduct_desc" TITLE="' .
+      encode_entities($ppt->description) .
+    '">' . encode_entities($ppt->taxproduct) . '</SPAN>'
+  };
+  my $taxproduct_list_sub = sub {
+    my $part_pkg = shift;
+    my $base_ppt = $part_pkg->taxproduct;
+    my $out = [];
+    if ( $base_ppt ) {
+      push @$out, [
+        { 'data'  => '', 'align' => 'left' },
+        { 'data'  => &$taxproduct_sub($base_ppt), 'align' => 'right' },
+      ];
+    }
+    for (my $i = 0; $i < scalar @classnums; $i++) {
+      my $num = $part_pkg->option('usage_taxproductnum_' . $classnums[$i]);
+      next if !$num;
+      my $ppt = FS::part_pkg_taxproduct->by_key($num);
+      push @$out, [
+        { 'data'  => $classnames[$i] . ': ', 'align' => 'left', },
+        { 'data'  => &$taxproduct_sub($ppt), 'align' => 'right' },
+      ];
+    }
+    $out;
+  };
+  push @fields, $taxproduct_list_sub;
+  $align .= 'l';
 }
 
 # make a table of report class optionnames =>  the actual 
@@ -602,7 +654,9 @@ push @fields,
                         sort
                         grep { $options{$_} =~ /\S/ } 
                         grep { $_ !~ /^(setup|recur)_fee$/ 
-                               and $_ !~ /^report_option_\d+$/ }
+                               and $_ !~ /^report_option_\d+$/
+                               and $_ !~ /^usage_taxproductnum_/
+                             }
                         keys %options
                       );
                       if ( @report_options ) {
diff --git a/httemplate/browse/part_pkg_taxproduct/suretax.html b/httemplate/browse/part_pkg_taxproduct/suretax.html
index 9c00c5c..8f237f3 100755
--- a/httemplate/browse/part_pkg_taxproduct/suretax.html
+++ b/httemplate/browse/part_pkg_taxproduct/suretax.html
@@ -138,8 +138,7 @@ my $id = $cgi->param('id');
 my $select_onclick = sub {
   my $row = shift;
   my $taxnum = $row->taxproductnum;
-  my $code = $row->taxproduct;
-  my $desc = $row->description;
+  my $desc = $row->taxproduct . ' ' . $row->description;
   "select_taxproduct('$taxnum', '$desc')";
 };
 
diff --git a/httemplate/elements/select-taxproduct.html b/httemplate/elements/select-taxproduct.html
index 5feb71d..d08ac22 100644
--- a/httemplate/elements/select-taxproduct.html
+++ b/httemplate/elements/select-taxproduct.html
@@ -1,14 +1,79 @@
-<% $opt{'prefix'} %><INPUT NAME    = "<% $name %>"
-                           ID      = "<% $name %>"
-                           TYPE    = "hidden"
-                           VALUE   = "<% $value |h %>"
-                    >
-                    <INPUT NAME    = "<% $name %>_description"
-                           ID      = "<% $name %>_description"
-                           TYPE    = "text"
-                           VALUE   = "<% $description %>"
-                           SIZE    = "12"
-                           onClick = "<% $onclick %>"><% $opt{'postfix'} %>
+% if (!$init) {
+%   $init = 1;
+<STYLE TYPE="text/css">
+.ui-autocomplete-loading {
+  background-color: silver;
+}
+ul.ui-autocomplete li.ui-menu-item {
+  font-size: 0.8em;
+  padding: 2px;
+}
+ul.ui-autocomplete li.ui-state-focus {
+  font-weight: normal;
+  color: #7e0079;
+  background-color: inherit;
+  border: 1px solid #7e0079;
+}
+</STYLE>
+<SCRIPT TYPE="text/javascript">
+$().ready(function() {
+  $('input.taxproduct_desc').autocomplete({
+    source: '<% $fsurl %>misc/taxproduct.cgi',
+    minLength: 3,
+    autoFocus: true,
+    response: function( event, ui ) {
+      // if there's only one choice (user entered an exact taxproduct) then
+      // select it
+      if ( ui.content.length == 1 ) {
+        var input_taxproductnum = $(this).siblings('.taxproductnum')
+        var item = ui.content[0];
+        $(this).val(item.label);
+        input_taxproductnum.val(item.value);
+      }
+    },
+    focus: function( event, ui ) {
+      return false;
+    },
+    select: function( event, ui ) {
+      // find the hidden input for the taxproductnum
+      var input_taxproductnum = $(this).siblings('.taxproductnum')
+      if ( ui.item ) {
+        $(this).val(ui.item.label);
+        input_taxproductnum.val(ui.item.value);
+        return false; // don't store item.value in this input
+      } else {
+        input_taxproductnum.val('');
+      }
+    },
+    change: function( event, ui ) {
+      var input_taxproductnum = $(this).siblings('.taxproductnum')
+      if ( $(this).val() == '' ) {
+        input_taxproductnum.val('');
+      }
+    }
+  });
+});
+</SCRIPT>
+% }
+<% $opt{'prefix'} %>
+<INPUT NAME    = "<% $name %>"
+       ID      = "<% $name %>"
+       TYPE    = "hidden"
+       VALUE   = "<% $value |h %>"
+       CLASS   = "taxproductnum"
+>
+<INPUT NAME    = "<% $name %>_description"
+       ID      = "<% $name %>_description"
+       TYPE    = "text"
+       VALUE   = "<% $description %>"
+       SIZE    = "50"
+       CLASS   = "taxproduct_desc" 
+>
+<BUTTON STYLE="padding: 0" onclick="<% $onclick %>">...</BUTTON>
+<% $opt{'postfix'} %>
+<%shared>
+my $init = 0;
+</%shared>
 <%init>
 
 my %opt = @_;
@@ -19,7 +84,8 @@ my $description = $opt{'taxproduct_description'};
 unless ( $description || ! $value ) {
     my $part_pkg_taxproduct =
       qsearchs( 'part_pkg_taxproduct', { 'taxproductnum'=> $value } );
-    $description = $part_pkg_taxproduct->description
+    $description = $part_pkg_taxproduct->taxproduct . ' ' .
+                   $part_pkg_taxproduct->description
       if $part_pkg_taxproduct;
 }
 
diff --git a/httemplate/elements/tr-part_pkg-taxproducts.html b/httemplate/elements/tr-part_pkg-taxproducts.html
index c57232c..5dcea09 100644
--- a/httemplate/elements/tr-part_pkg-taxproducts.html
+++ b/httemplate/elements/tr-part_pkg-taxproducts.html
@@ -1,18 +1,39 @@
+%# by default, only show default
 <TR>
-  <TH COLSPAN=2>Tax products</TH>
+  <TH ALIGN="right"><% emt('Tax product') %></TH>
+  <TD><& select-taxproduct.html,
+        %opt,
+        'field'       => $field.'_', # expected in edit/process/part_pkg
+        'curr_value'  => $curr_values{''},
+      &>
+  </TD>
+</TR>
+% if ( !$separate ) {
+<TR STYLE="font-size: small">
+  <TD></TD>
+  <TD>
+  <BUTTON TYPE="button" ID="show_taxproduct_class">By usage class
+    <IMG SRC="<%$fsurl%>images/arrow.down.black.png">
+  </BUTTON>
+  </TD>
 </TR>
+<SCRIPT TYPE="text/javascript">
+$().ready(function() {
+  $('#show_taxproduct_class').on('click', function() {
+    this.disabled = true;
+    $('tr.taxproduct_class').show();
+  });
+});
+</SCRIPT>
+% }
 % foreach my $usage_class (@classes) {
 %   my $classnum = $usage_class->classnum;
-%   my $curr_value =
-%        $cgi->param("usage_taxproductnum_$classnum")
-%     || $pkg_options{"usage_taxproductnum_$classnum"}
-%     || '';
-<TR>
-  <TD><% $usage_class->classname %></TD>
+<TR CLASS="taxproduct_class" STYLE="<% $separate ? '' : 'display:none' %>">
+  <TH ALIGN="right"><% $usage_class->classname %></TH>
   <TD><& select-taxproduct.html,
         %opt,
         'field'       => $field.'_'.$classnum,
-        'curr_value'  => $curr_value
+        'curr_value'  => $curr_values{$classnum},
       &>
   </TD>
 </TR>
@@ -20,18 +41,29 @@
 <%init>
 my %opt = @_;
 my $field = delete($opt{field}) || 'taxproductnum';
+my @classes = qsearch('usage_class', { 'disabled' => '' });
+unshift @classes,
+  FS::usage_class->new({ 'classnum' => 'setup', 'classname' => 'Setup', }),
+  FS::usage_class->new({ 'classnum' => 'recur', 'classname' => 'Recur', }),
+;
+my $separate = 0; # will change to 1 if any non-default classes have values
+
 my $pkgpart = delete($opt{pkgpart});
+my %curr_values;
 my %pkg_options;
 if ($pkgpart) {
   my $part_pkg = FS::part_pkg->by_key($pkgpart);
   %pkg_options = $part_pkg->options;
-  $pkg_options{'usage_taxproductnum_'} = $part_pkg->taxproductnum;
+  $curr_values{''} = $part_pkg->taxproductnum;
 }
 
-my @classes = qsearch('usage_class', { 'disabled' => '' });
-unshift @classes,
-  FS::usage_class->new({ 'classnum' => '', 'classname' => '(default)', }),
-  FS::usage_class->new({ 'classnum' => 'setup', 'classname' => 'Setup', }),
-  FS::usage_class->new({ 'classnum' => 'recur', 'classname' => 'Recur', }),
-;
+foreach my $usage_class (@classes) {
+  my $classnum = $usage_class->classnum;
+  my $curr_value =
+       $cgi->param("usage_taxproductnum_$classnum")
+    || $pkg_options{"usage_taxproductnum_$classnum"}
+    || '';
+  $curr_values{$classnum} = $curr_value;
+  $separate = 1 if ( length($classnum) and length($curr_value) );
+}
 </%init>
diff --git a/httemplate/misc/taxproduct.cgi b/httemplate/misc/taxproduct.cgi
new file mode 100644
index 0000000..b228493
--- /dev/null
+++ b/httemplate/misc/taxproduct.cgi
@@ -0,0 +1,24 @@
+<%once>
+my $conf = FS::Conf->new;
+my $vendor = $conf->config('tax_data_vendor');
+</%once>
+<%init>
+my $term = $cgi->param('term');
+warn "taxproduct.cgi?$term"; # XXX debug
+my $search = { table => 'part_pkg_taxproduct' };
+if ( $term =~ /^\d+$/ ) {
+  $search->{extra_sql} = " WHERE taxproduct LIKE '$term%'";
+  $search->{order_by} = " ORDER BY taxproduct ASC";
+} elsif ( length($term) ) {
+  $term = dbh->quote( lc($term) ); # protect against bad strings
+  $search->{extra_sql} = " WHERE POSITION($term IN LOWER(description)) > 0";
+  # and sort by how close to the beginning of the string it is
+  $search->{order_by} = " ORDER BY POSITION($term IN LOWER(description)) ASC, LOWER(description) ASC, taxproduct ASC";
+}
+my @taxproducts = qsearch($search);
+my @results = map {
+  { label => $_->taxproduct . ' ' . $_->description,
+    value => $_->taxproductnum } 
+} @taxproducts;
+</%init>
+<% encode_json(\@results) %>\

-----------------------------------------------------------------------

Summary of changes:
 httemplate/browse/part_pkg.cgi                     |   56 +++++++++++-
 httemplate/browse/part_pkg_taxproduct/suretax.html |    3 +-
 httemplate/elements/select-taxproduct.html         |   90 +++++++++++++++++---
 httemplate/elements/tr-part_pkg-taxproducts.html   |   62 ++++++++++----
 httemplate/misc/taxproduct.cgi                     |   24 ++++++
 5 files changed, 205 insertions(+), 30 deletions(-)
 create mode 100644 httemplate/misc/taxproduct.cgi




More information about the freeside-commits mailing list