diff options
Diffstat (limited to 'FS/FS/Cron/tax_rate_update.pm')
-rwxr-xr-x | FS/FS/Cron/tax_rate_update.pm | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/FS/FS/Cron/tax_rate_update.pm b/FS/FS/Cron/tax_rate_update.pm new file mode 100755 index 000000000..e345964e8 --- /dev/null +++ b/FS/FS/Cron/tax_rate_update.pm @@ -0,0 +1,111 @@ +#!/usr/bin/perl + +=head1 NAME + +FS::Cron::tax_rate_update + +=head1 DESCRIPTION + +Cron routine to update city/district sales tax rates in I<cust_main_county>. +Currently supports sales tax in the state of Washington. + +=cut + +use strict; +use warnings; +use FS::Conf; +use FS::Record qw(qsearch qsearchs dbh); +use FS::cust_main_county; +use FS::part_pkg_taxclass; +use DateTime; +use LWP::UserAgent; +use File::Temp 'tempdir'; +use File::Slurp qw(read_file write_file); +use Text::CSV; +use Exporter; + +our @EXPORT_OK = qw(tax_rate_update); +our $DEBUG = 0; + +sub tax_rate_update { + my %opt = @_; + + my $oldAutoCommit = $FS::UID::AutoCommit; + $FS::UID::AutoCommit = 0; + my $dbh = dbh; + + my $conf = FS::Conf->new; + my $method = $conf->config('tax_district_method'); + return if !$method; + + my $taxname = $conf->config('tax_district_taxname') || ''; + + if ($method eq 'wa_sales') { + # download the update file + my $now = DateTime->now; + my $yr = $now->year; + my $qt = $now->quarter; + my $file = "Rates${yr}Q${qt}.zip"; + my $url = 'http://dor.wa.gov/downloads/Add_Data/'.$file; + my $dir = tempdir(); + chdir($dir); + my $ua = LWP::UserAgent->new; + warn "Downloading $url...\n" if $DEBUG; + my $response = $ua->get($url); + if ( ! $response->is_success ) { + die $response->status_line; + } + write_file($file, $response->decoded_content); + + # parse it + system('unzip', $file); + $file =~ s/\.zip$/.csv/; + if (! -f $file) { + die "$file not found in zip archive.\n"; + } + open my $fh, '<', $file + or die "couldn't open $file: $!\n"; + my $csv = Text::CSV->new; + my $header = $csv->getline($fh); + $csv->column_names(@$header); + # columns we care about are headed 'Code' and 'Rate' + + my $total_changed = 0; + my $total_skipped = 0; + while ( !$csv->eof ) { + my $line = $csv->getline_hr($fh); + my $district = $line->{Code} or next; + $district = sprintf('%04d', $district); + my $tax = sprintf('%.1f', $line->{Rate} * 100); + my $changed = 0; + my $skipped = 0; + # find rate(s) in this country+state+district+taxclass that have the + # wa_sales flag and the configured taxname, and haven't been disabled. + my @rates = qsearch('cust_main_county', { + country => 'US', + state => 'WA', # this is specific to WA + district => $district, + taxname => $taxname, + source => 'wa_sales', + tax => { op => '>', value => '0' }, + }); + foreach my $rate (@rates) { + if ( $rate->tax == $tax ) { + $skipped++; + } else { + $rate->set('tax', $tax); + my $error = $rate->replace; + die "error updating district $district: $error\n" if $error; + $changed++; + } + } # foreach $taxclass + print "$district: updated $changed, skipped $skipped\n" + if $DEBUG and ($changed or $skipped); + $total_changed += $changed; + $total_skipped += $skipped; + } + print "Updated $total_changed tax rates.\nSkipped $total_skipped unchanged rates.\n" if $DEBUG; + dbh->commit; + } # else $method isn't wa_sales, no other methods exist yet + ''; +} |