RT# 80488 Live look up of WA state tax district
authorMitch Jackson <mitch@freeside.biz>
Sat, 19 Jan 2019 12:41:08 +0000 (07:41 -0500)
committerMitch Jackson <mitch@freeside.biz>
Sun, 20 Jan 2019 21:44:06 +0000 (16:44 -0500)
When conf flag 'tax_district_method' is set, tax district
is queried for address before form is submitted

Affected Pages:
* New Customer
* Edit Customer
* Order Package
* Change Package
* Edit Package Location

FS/FS/cust_location.pm
FS/FS/cust_main.pm
httemplate/edit/cust_location.cgi
httemplate/edit/cust_main/bottomfixup.js
httemplate/elements/tr-select-cust_location.html
httemplate/elements/wa_state_tax_district.js [new file with mode: 0644]
httemplate/misc/change_pkg.cgi
httemplate/misc/order_pkg.html
httemplate/misc/xmlhttp-wa_state-find_district_for_address.html [new file with mode: 0644]

index e1b8533..4521bd3 100644 (file)
@@ -265,8 +265,15 @@ sub insert {
     return $error;
   }
 
-  #false laziness with cust_main, will go away eventually
-  if ( !$import and $conf->config('tax_district_method') ) {
+  # If using tax_district_method, for rows in state of Washington,
+  # without a tax district already specified, queue a job to find
+  # the tax district
+  if (
+       !$import
+    && !$self->district
+    && lc $self->state eq 'wa'
+    && $conf->config('tax_district_method')
+  ) {
 
     my $queue = new FS::queue {
       'job' => 'FS::geocode_Mixin::process_district_update'
@@ -943,7 +950,11 @@ sub _upgrade_data {
       die "$error (fixing whitespace in $field, locationnum ".$location->locationnum.')'
         if $error;
 
-      if ( $use_districts ) {
+      if (
+        $use_districts
+        && !$location->district
+        && lc $location->state eq 'wa'
+      ) {
         my $queue = new FS::queue {
           'job' => 'FS::geocode_Mixin::process_district_update'
         };
index afc21a9..d42bd81 100644 (file)
@@ -743,20 +743,6 @@ sub insert {
     }
   }
 
-  # FS::geocode_Mixin::after_insert or something?
-  if ( $conf->config('tax_district_method') and !$import ) {
-    # if anything non-empty, try to look it up
-    my $queue = new FS::queue {
-      'job'     => 'FS::geocode_Mixin::process_district_update',
-      'custnum' => $self->custnum,
-    };
-    my $error = $queue->insert( ref($self), $self->custnum );
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return "queueing tax district update: $error";
-    }
-  }
-
   # cust_main exports!
   warn "  exporting\n" if $DEBUG > 1;
 
index 38816db..93311c5 100755 (executable)
@@ -17,10 +17,21 @@ ACTION="<% $p %>edit/process/cust_location.cgi" METHOD=POST>
 &>
 <& /elements/standardize_locations.html,
             'form'          => 'EditLocationForm',
-            'callback'      => 'document.EditLocationForm.submit();',
+            'callback'    => $conf->exists('tax_district_method')
+                              ? 'wa_state_tax_district()'
+                              : 'submit_continue()',
             'with_census'   => 1,
             'with_census_functions' => 1,
 &>
+<script>
+  <& /elements/wa_state_tax_district.js &>
+
+  // wa_sate_tax_district() will call submit_continue() upon success,
+  //   or submit_abort() upon error
+  function submit_continue() {
+    document.EditLocationForm.submit();
+  }
+</script>
 </TABLE>
 
 <BR>
index 97816aa..d2a277b 100644 (file)
@@ -7,6 +7,9 @@ my $company_longitude = $conf->config('company_longitude');
 
 my @fixups = ('standardize_locations');
 
+push @fixups, 'wa_state_tax_district'
+  if $conf->exists('tax_district_method');
+
 push @fixups, 'confirm_censustract_bill', 'confirm_censustract_ship'
     if $conf->exists('cust_main-require_censustract');
 
@@ -57,6 +60,8 @@ function do_submit() {
   'with_census' => 1, # no with_firm, apparently
 &>
 
+<& /elements/wa_state_tax_district.js &>
+
 % # the value in pre+'censustract' is the confirmed censustract (either from
 % # the previous saved record, or from address standardization (if the backend
 % # supports it), or from an aborted previous submit. only need to reconfirm
index 7a2d886..1e6cf5b 100644 (file)
@@ -202,6 +202,7 @@ Example:
      'alt_format'         => $opt{'alt_format'},
      'enable_coords'      => 1,
      'enable_censustract' => 1,
+     'enable_district'    => $conf->exists('tax_district_method') ? 1 : 0,
 &>
 
 <SCRIPT TYPE="text/javascript">
diff --git a/httemplate/elements/wa_state_tax_district.js b/httemplate/elements/wa_state_tax_district.js
new file mode 100644 (file)
index 0000000..03f262b
--- /dev/null
@@ -0,0 +1,159 @@
+<%doc>
+
+Provide js function in support of a lookup hook for wa_state_tax_districts
+
+wa_state_tax_district()
+* Checks form_address_info() to collect address data
+* If any addresses are in Washington State,
+* Uses misc/xmlhttp-wa_state-find_district_for_address.html to query
+  wa state tax districting database
+* Displays error, or updates the district input element for the addresses
+* Calls submit_continue() upon success
+* Calls submit_abort() upon error
+
+</%doc>
+
+function wa_state_tax_district() {
+  // Queries the WA State API to get a Tax District for this address
+  // upon failure: User can choose to skip or cancel
+  // upon success: set value of district input box and submit_continue()
+
+  address_info = form_address_info();
+  // console.log( address_info );
+
+  if (
+       address_info['state'] != 'WA'
+    && address_info['state'] != 'wa'
+    && address_info['bill_state'] != 'WA'
+    && address_info['bill_state'] != 'wa'
+    && (
+      address_info['same']
+      || (
+        address_info['ship_state'] != 'WA'
+        && address_info['ship_state'] != 'wa'
+      )
+    )
+  ) {
+    // nothing to do, not in Washington state
+    submit_continue();
+    return;
+  }
+
+  wa_state_tax_district_overlib( 'Looking up tax district... please wait...' );
+
+  $.post({
+    url: "<% $fsurl %>misc/xmlhttp-wa_state-find_district_for_address.html",
+    data: address_info,
+    success: function(response) {
+      // console.log(response);
+
+      let error = '';
+      if ( response['error'] ) {
+        error = error + response['error'] + ' ';
+      }
+
+      // populate Billing Address district into form, or record error
+      if ( response['bill'] && response['bill']['district'] ) {
+        $('#bill_district').val( response['bill']['district'] );
+      }
+      else if ( response['bill'] && response['bill']['error'] ) {
+        error = error + 'Cound not set tax district for billing address. ';
+      }
+
+      // populate Shipping Address district into form, or record error
+      if (
+        ! address_info['same']
+        && response['ship']
+        && response['ship']['district']
+      ) {
+        $('#ship_district').val( response['ship']['district'] );
+      }
+      else if (
+        ! address_info['same']
+        && response['ship']
+        && response['ship']['error']
+      ) {
+        error = error + 'Could not set tax district for service address. ';
+      }
+
+      // populate Plain Address district into form, or record error
+      if (
+        response['address']
+        && response['address']['district']
+      ) {
+        $('#district').val( response['address']['district'] );
+      }
+      else if (
+        response['address']
+        && response['address']['error']
+      ) {
+        error = error + 'Could not set tax district for address. ';
+      }
+
+      if ( error ) {
+        wa_state_tax_district_overlib(
+          'An error occured determining Washington state tax district:<br>'
+          + '<br>'
+          + error + '<br>'
+          + '<br>'
+          + 'If you choose to skip this step, taxes will not be calculated '
+          + 'for this customer, unless you enter a tax district manually.'
+          + '<br>'
+          + '<a href="https://webgis.dor.wa.gov/taxratelookup/SalesTax.aspx" target="_blank">See WA Dept of Revenue</a>'
+        );
+      }
+      else {
+        cClick();
+        submit_continue();
+        return;
+      }
+
+    }
+  })
+  .fail(function() {
+    wa_state_tax_district_overlib(
+      'A network error occured determining Washington state tax district:<br>'
+      + '<br>'
+      + 'If you choose to skip this step, taxes will not be calculated '
+      + 'for this customer, unless you enter a tax district manually.'
+      + '<br>'
+      + '<a href="https://webgis.dor.wa.gov/taxratelookup/SalesTax.aspx" target="_blank">See WA Dept of Revenue</a>'
+    );
+  });
+}
+
+function wa_state_tax_district_overlib(html) {
+  html =
+      '<div style="text-align: center;">'
+    +   '<h2>Washington State Tax District Lookup</h2>'
+    +   '<p>' + html + '</p>'
+    + '<a href="#" onclick="wa_state_tax_district_skip()">skip</a>'
+    + ' | '
+    + '<a href="#" onclick="wa_state_tax_district_cancel()">cancel</a>'
+    + '</div>';
+
+  overlib(
+    html,
+    CAPTION, 'WA State Tax District',
+    STICKY,
+    CLOSETEXT, '',
+    MIDX, 0,
+    MIDY, 0,
+    WIDTH, 500,
+    BGCOLOR, '#339',
+    CGCOLOR, '#339',
+    TEXTSIZE, 3
+  );
+}
+
+function wa_state_tax_district_skip() {
+  // Click target to skip tax district determination
+  cClick()
+  submit_continue();
+}
+
+function wa_state_tax_district_cancel() {
+  // Click target to cancel submit from tax district determination
+  cClick()
+  submit_abort();
+}
index c588c9e..9729c6b 100755 (executable)
             'form'        => "OrderPkgForm",
             'with_census' => 1,
             'with_census_functions' => 1,
-            'callback'   => 'document.OrderPkgForm.submit()',
+            'callback'    => $conf->exists('tax_district_method')
+                              ? 'wa_state_tax_district()'
+                              : 'submit_continue()',
 &>
 
+<script>
+  <& /elements/wa_state_tax_district.js &>
+
+  // wa_sate_tax_district() will call submit_continue() upon success,
+  //   or submit_abort() upon error
+  function submit_continue() {
+    document.OrderPkgForm.submit();
+  }
+</script>
+
 <INPUT NAME    = "submitButton"
        TYPE    = "button"
        VALUE   = "<% mt("Change package") |h %>"
index 1efe745..7a63b5c 100644 (file)
 
   <& /elements/standardize_locations.html,
                 'form'        => "OrderPkgForm",
-                'callback'    => 'document.OrderPkgForm.submit()',
+                'callback'    => $conf->exists('tax_district_method')
+                                 ? 'wa_state_tax_district()'
+                                 : 'submit_continue()',
                 'with_census' => 1,
                 'with_census_functions' => 1,
   &>
 
+  <script>
+    <& /elements/wa_state_tax_district.js &>
+
+    // wa_sate_tax_district() will call submit_continue() upon success,
+    //   or submit_abort() upon error
+    function submit_continue() {
+      document.OrderPkgForm.submit();
+    }
+  </script>
+
 % }
 
 % if ($quotationnum) {
diff --git a/httemplate/misc/xmlhttp-wa_state-find_district_for_address.html b/httemplate/misc/xmlhttp-wa_state-find_district_for_address.html
new file mode 100644 (file)
index 0000000..e59789b
--- /dev/null
@@ -0,0 +1,76 @@
+<%doc>
+
+Expects POST keys:
+* address1
+* address2
+* city
+* state
+* zip
+* country
+
+Also accepts all the above keys with the prefixes bill_ and ship_
+
+Returns json with a key for each given address, e.g., whose value is
+the tax district number. e.g.
+{
+  address: {
+    district: 1234
+    tax: 7.9
+    exempt_amount: 0
+    city: MOXEE CITY
+    state: WA
+  },
+  bill: {
+    error: district not found
+    district:
+  },
+}
+
+</%doc>
+<% encode_json($return) %>
+<%init>
+use Data::Dumper;
+use FS::Misc::Geo;
+
+http_header('Content-Type' => 'application/json');
+
+my $DEBUG = 0;
+my %param = ( $cgi->Vars );
+my $return = {};
+
+warn '$param: '.Dumper( \%param )."\n"
+  if $DEBUG;
+
+my %address;
+for my $prefix ( '', 'bill', 'ship' ) {
+  my $addr_key = $prefix || 'address';
+  $address{$addr_key} = {};
+  $address{$addr_key}->{$_} = $param{ $prefix ? "${prefix}_${_}" : $_ }
+    for qw/ address1 address2 city state zip country /;
+  delete $address{$addr_key}
+    unless $address{$addr_key}->{address1}
+        && $address{$addr_key}->{city};
+}
+warn Dumper( \%address )
+  if $DEBUG;
+
+for my $k ( keys %address ) {
+  next unless lc $address{$k}->{state} eq 'wa';
+  my $response = FS::Misc::Geo::wa_sales( $address{$k} );
+  warn Dumper( $response )
+    if $DEBUG;
+
+  if ( ref $response ) {
+    $return->{$k} = $response;
+  } else {
+    $return->{$k} = { error => 'Lookup Failed' };
+  }
+}
+
+unless ( keys %$return ) {
+  $return->{error} = 'No WA addresses passed for lookup - nothing to do';
+}
+
+warn '$return: '.Dumper( $return )."\n"
+  if $DEBUG;
+</%init>