add Avalara tax status field to prospects, #25718
authorMark Wells <mark@freeside.biz>
Mon, 20 Apr 2015 07:48:29 +0000 (00:48 -0700)
committerMark Wells <mark@freeside.biz>
Mon, 20 Apr 2015 16:43:00 +0000 (09:43 -0700)
FS/FS/Schema.pm
FS/FS/TaxEngine/avalara.pm
FS/FS/prospect_main.pm
httemplate/edit/prospect_main.html
httemplate/view/prospect_main.html

index 29bbf78..7f28e11 100644 (file)
@@ -1643,7 +1643,7 @@ sub tables_hashref {
         'message_noemail', 'char', 'NULL', 1, '', '',
         'bill_locationnum', 'int', 'NULL', '', '', '',
         'ship_locationnum', 'int', 'NULL', '', '', '',
-        'taxstatusnum',   'char', 'NULL',      32, '', '',
+        'taxstatusnum',   'int', 'NULL', '', '', '',
         'complimentary', 'char', 'NULL', 1, '', '',
         'po_number', 'varchar', 'NULL', $char_d, '', '',
         'invoice_attn', 'varchar', 'NULL', $char_d, '', '',
@@ -1885,6 +1885,7 @@ sub tables_hashref {
         'disabled',       'char', 'NULL',       1, '', '', 
         'custnum',         'int', 'NULL',      '', '', '',
         'refnum',          'int', 'NULL',      '', '', '', 
+        'taxstatusnum',    'int', 'NULL',      '', '', '',
       ],
       'primary_key'  => 'prospectnum',
       'unique'       => [],
@@ -1987,12 +1988,10 @@ sub tables_hashref {
         'quotationtaxnum',  'serial',     '',      '', '', '',
         'quotationpkgnum',     'int',     '',      '', '', '',
         'itemdesc',        'varchar',     '', $char_d, '', '',
-        'taxnum',              'int',     '',      '', '', '', 
-        'taxtype',         'varchar',     '', $char_d, '', '',
         'setup_amount',    @money_type,                '', '',
         'recur_amount',    @money_type,                '', '',
       ],
-      'primary_key' => 'quotationtaxnum',,
+      'primary_key' => 'quotationtaxnum',
       'unique' => [],
       'index'  => [ [ 'quotationpkgnum' ] ],
       'foreign_keys' => [
@@ -2000,7 +1999,7 @@ sub tables_hashref {
                             table      => 'quotation_pkg',
                           },
                         ],
-},
+    },
 
     'cust_location' => { #'location' now that its prospects too, but...
       'columns' => [
index 183555d..d4a2360 100644 (file)
@@ -11,7 +11,7 @@ use FS::tax_rate;
 use JSON;
 use Geo::StreetAddress::US;
 
-our $DEBUG = 2;
+our $DEBUG = 0;
 our $json = JSON->new->pretty(1);
 
 our $conf;
@@ -29,10 +29,6 @@ FS::UID->install_callback( sub {
 #}
 # Avalara address standardization would be nice but isn't necessary
 
-# XXX this is just here to avoid reworking the framework right now. By the
-# 4.0 release, ALL tax calculations should be done after the invoice has 
-# been inserted into the database.
-
 # nothing to do here
 sub add_sale {}
 
@@ -85,6 +81,8 @@ sub build_request {
     };
     push @lines, $line;
   }
+  # don't make the request unless there are some eligible line items
+  return '' if !@lines;
 
   # assemble address records for any cust_locations we used here, plus
   # the company address
@@ -141,6 +139,7 @@ sub build_request {
 
   # create the top level object
   my $date = DateTime->from_epoch(epoch => $self->{invoice_time});
+  my $doctype = $self->{estimate} ? 'SalesOrder' : 'SalesInvoice';
   return {
     'CustomerCode'      => $cust_main->custnum,
     'DocDate'           => $date->strftime('%Y-%m-%d'),
@@ -149,7 +148,7 @@ sub build_request {
     'DocCode'           => $cust_bill->invnum,
     'DetailLevel'       => 'Tax',
     'Commit'            => 'false',
-    'DocType'           => 'SalesInvoice', # ???
+    'DocType'           => $doctype,
     'CustomerUsageType' => $cust_main->taxstatus,
     # ExemptionNo, Discount, TaxOverride, PurchaseOrderNo,
     'Addresses'         => \@addrs,
@@ -196,6 +195,10 @@ account number, and license key.
 
   # assemble the request hash
   my $request = $self->build_request;
+  if (!$request) {
+    warn "no tax-eligible items on this invoice\n" if $DEBUG;
+    return [];
+  }
 
   warn "sending Avalara tax request\n" if $DEBUG;
   my $request_json = $json->encode($request);
@@ -247,6 +250,7 @@ account number, and license key.
       my $error = $tax_rate->find_or_insert;
       return "error inserting tax_rate record for '$taxname': $error\n"
         if $error;
+      $tax_rate = $tax_rate->replace_old; # get its taxnum if there wasn't one
 
       # create a tax_rate_location record
       my $tax_rate_location = FS::tax_rate_location->new({
@@ -266,7 +270,7 @@ account number, and license key.
 
       # create a link record
       my $tax_link = FS::cust_bill_pkg_tax_rate_location->new({
-          cust_bill_pkg       => $tax_item,
+          tax_cust_bill_pkg   => $tax_item,
           taxtype             => 'FS::tax_rate',
           taxnum              => $tax_rate->taxnum,
           taxratelocationnum  => $tax_rate_location->taxratelocationnum,
index 7c58de3..79efa86 100644 (file)
@@ -5,7 +5,7 @@ use strict;
 use vars qw( $DEBUG @location_fields );
 use Scalar::Util qw( blessed );
 use FS::Conf;
-use FS::Record qw( dbh qsearch ); # qsearchs );
+use FS::Record qw( dbh qsearch qsearchs );
 use FS::cust_location;
 use FS::cust_main;
 
@@ -246,6 +246,7 @@ sub check {
     || $self->ut_foreign_key(  'agentnum', 'agent',         'agentnum' )
     || $self->ut_foreign_keyn( 'refnum',   'part_referral', 'refnum'   )
     || $self->ut_textn('company')
+    || $self->ut_foreign_keyn( 'taxstatusnum', 'tax_status', 'taxstatusnum' )
   ;
   return $error if $error;
 
@@ -299,6 +300,36 @@ Returns the qualifications (see L<FS::qual>) associated with this prospect.
 
 Returns the agent (see L<FS::agent>) for this customer.
 
+=item tax_status
+
+Returns the external tax status, as an FS::tax_status object, or the empty 
+string if there is no tax status.
+
+=cut
+
+sub tax_status {
+  my $self = shift;
+  if ( $self->taxstatusnum ) {
+    qsearchs('tax_status', { 'taxstatusnum' => $self->taxstatusnum } );
+  } else { 
+    return '';
+  }
+}
+
+=item taxstatus
+
+Returns the tax status code if there is one.
+
+=cut
+
+sub taxstatus {
+  my $self = shift;
+  my $tax_status = $self->tax_status;
+  $tax_status
+    ? $tax_status->taxstatus
+    : '';
+}
+
 =item convert_cust_main
 
 Converts this prospect to a customer.
@@ -325,7 +356,7 @@ sub convert_cust_main {
   my $cust_main = new FS::cust_main {
     'bill_location' => $cust_location[0],
     'ship_location' => $cust_location[0],
-    ( map { $_ => $self->$_ } qw( agentnum refnum company ) ),
+    ( map { $_ => $self->$_ } qw( agentnum refnum company taxstatusnum ) ),
   };
 
   $cust_main->refnum( FS::Conf->new->config('referraldefault') || 1  )
@@ -410,6 +441,11 @@ sub cust_bill {
   return;
 }
 
+# XXX should have real localization here eventually
+sub locale {
+  FS::Conf->new->config('locale');
+}
+
 =back
 
 =head1 BUGS
index da5c6ce..1269a84 100644 (file)
@@ -7,6 +7,7 @@
                             'company'     => 'Company',
                             'contactnum'  => 'Contact',
                             'locationnum' => '&nbsp;',
+                            'taxstatusnum'=> 'Tax status',
                           },
      'fields'          => [
        { 'field'       => 'agentnum',
             'prospect_main' => shift
           },
        },
+       { 'field'    => 'taxstatusnum',
+         'type'     => 'select-tax_status',
+         'empty_label'   => ' ',
+       },
      ],
      'new_callback'    => $new_callback,
      'edit_callback'   => $edit_callback,
index a1f14a3..b5ef64f 100644 (file)
       &>
 %   }
 % }
+% if ( my $tax_status = $prospect_main->tax_status ) {
+  <TR>
+    <TD ALIGN="right">Tax status</TD>
+    <TD BGCOLOR="#FFFFFF">
+      <B><% $tax_status->taxstatus %>:</B> <% $tax_status->description %>
+    </TD>
+  </TR>
+% }
 
 </TABLE>