From f2cf5c2843dcef5db0941a1673538eb922fd5a5a Mon Sep 17 00:00:00 2001 From: Mark Wells Date: Mon, 20 Apr 2015 00:48:29 -0700 Subject: [PATCH] add Avalara tax status field to prospects, #25718 --- FS/FS/Schema.pm | 9 ++++----- FS/FS/TaxEngine/avalara.pm | 18 ++++++++++------- FS/FS/prospect_main.pm | 40 ++++++++++++++++++++++++++++++++++++-- httemplate/edit/prospect_main.html | 5 +++++ httemplate/view/prospect_main.html | 8 ++++++++ 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 29bbf7809..7f28e11f7 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -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' => [ diff --git a/FS/FS/TaxEngine/avalara.pm b/FS/FS/TaxEngine/avalara.pm index 183555d88..d4a23602c 100644 --- a/FS/FS/TaxEngine/avalara.pm +++ b/FS/FS/TaxEngine/avalara.pm @@ -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, diff --git a/FS/FS/prospect_main.pm b/FS/FS/prospect_main.pm index 7c58de304..79efa86d0 100644 --- a/FS/FS/prospect_main.pm +++ b/FS/FS/prospect_main.pm @@ -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) associated with this prospect. Returns the agent (see L) 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 diff --git a/httemplate/edit/prospect_main.html b/httemplate/edit/prospect_main.html index da5c6ce37..1269a84ed 100644 --- a/httemplate/edit/prospect_main.html +++ b/httemplate/edit/prospect_main.html @@ -7,6 +7,7 @@ 'company' => 'Company', 'contactnum' => 'Contact', 'locationnum' => ' ', + 'taxstatusnum'=> 'Tax status', }, 'fields' => [ { 'field' => 'agentnum', @@ -46,6 +47,10 @@ 'prospect_main' => shift }, }, + { 'field' => 'taxstatusnum', + 'type' => 'select-tax_status', + 'empty_label' => ' ', + }, ], 'new_callback' => $new_callback, 'edit_callback' => $edit_callback, diff --git a/httemplate/view/prospect_main.html b/httemplate/view/prospect_main.html index a1f14a374..b5ef64f48 100644 --- a/httemplate/view/prospect_main.html +++ b/httemplate/view/prospect_main.html @@ -69,6 +69,14 @@ &> % } % } +% if ( my $tax_status = $prospect_main->tax_status ) { + + Tax status + + <% $tax_status->taxstatus %>: <% $tax_status->description %> + + +% } -- 2.11.0