X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2FTaxEngine%2Favalara.pm;h=cb841c373e370795c8972a222feb65cc6571830e;hb=ffa18709ee8a4d05e18d2d406cf73afe79e52524;hp=183555d88dcca6a64ef7bd65f6daa4be5b29dade;hpb=7516e3da0f17eeecba27219ef96a8b5f46af2083;p=freeside.git diff --git a/FS/FS/TaxEngine/avalara.pm b/FS/FS/TaxEngine/avalara.pm index 183555d88..cb841c373 100644 --- a/FS/FS/TaxEngine/avalara.pm +++ b/FS/FS/TaxEngine/avalara.pm @@ -8,11 +8,11 @@ use FS::cust_pkg; use FS::cust_location; use FS::cust_bill_pkg; use FS::tax_rate; -use JSON; +use Cpanel::JSON::XS; use Geo::StreetAddress::US; -our $DEBUG = 2; -our $json = JSON->new->pretty(1); +our $DEBUG = 0; +our $json = Cpanel::JSON::XS->new->pretty(1); our $conf; @@ -29,20 +29,12 @@ 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 {} sub build_request { my ($self, %opt) = @_; - my $oldAutoCommit = $FS::UID::AutoCommit; - local $FS::UID::AutoCommit = 0; - my $dbh = dbh; - my $cust_bill = $self->{cust_bill}; my $cust_main = $cust_bill->cust_main; @@ -85,6 +77,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 @@ -92,7 +86,13 @@ sub build_request { my $our_address = join(' ', $conf->config('company_address', $cust_main->agentnum) ); - my $company_address = Geo::StreetAddress::US->parse_address($our_address); + my $company_address = Geo::StreetAddress::US->parse_location($our_address); + if (!$company_address->{street} + or !$company_address->{city} + or !$company_address->{zip}) { + die "Your company address could not be parsed. Avalara tax calculation requires a company address with street, city, and zip code.\n"; + } + my $address1 = join(' ', grep $_, @{$company_address}{qw( number prefix street type suffix )}); @@ -141,6 +141,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 +150,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, @@ -163,8 +164,8 @@ sub calculate_taxes { my $cust_bill = shift; if (!$cust_bill->invnum) { - warn "FS::TaxEngine::avalara: can't calculate taxes on a non-inserted invoice"; - return; + # then something is wrong + die "FS::TaxEngine::avalara: can't calculate taxes on a non-inserted invoice\n"; } $self->{cust_bill} = $cust_bill; @@ -196,6 +197,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); @@ -209,8 +214,9 @@ account number, and license key. my %tax_item_named; if ( $response->{ResultCode} ne 'Success' ) { - return "invoice#".$cust_bill->invnum.": ". - join("\n", @{ $response->{Messages} }); + die "Avalara tax error on invoice#".$cust_bill->invnum.": ". + join("\n", @{ $response->{Messages} }). + "\n"; } warn "creating taxes for inv#$invnum\n" if $DEBUG > 1; foreach my $TaxLine (@{ $response->{TaxLines} }) { @@ -245,8 +251,9 @@ account number, and license key. fee => 0, }); my $error = $tax_rate->find_or_insert; - return "error inserting tax_rate record for '$taxname': $error\n" + die "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({ @@ -260,13 +267,13 @@ account number, and license key. # country? }); $error = $tax_rate_location->find_or_insert; - return "error inserting tax_rate_location record for ". + die "error inserting tax_rate_location record for ". $TaxDetail->{JurisCode} .": $error\n" if $error; # 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,