5 FS::Cron::tax_rate_update
9 Cron routine to update city/district sales tax rates in I<cust_main_county>.
10 Currently supports sales tax in the state of Washington.
17 use FS::Record qw(qsearch qsearchs dbh);
18 use FS::cust_main_county;
19 use FS::part_pkg_taxclass;
22 use File::Temp 'tempdir';
23 use File::Slurp qw(read_file write_file);
27 our @EXPORT_OK = qw(tax_rate_update);
33 my $oldAutoCommit = $FS::UID::AutoCommit;
34 $FS::UID::AutoCommit = 0;
37 my $conf = FS::Conf->new;
38 my $method = $conf->config('tax_district_method');
41 my $taxname = $conf->config('tax_district_taxname') || '';
43 FS::cust_main_county->lock_table;
44 if ($method eq 'wa_sales') {
45 # download the update file
46 my $now = DateTime->now;
48 my $qt = $now->quarter;
49 my $file = "Rates${yr}Q${qt}.zip";
50 my $url = 'http://dor.wa.gov/downloads/Add_Data/'.$file;
53 my $ua = LWP::UserAgent->new;
54 warn "Downloading $url...\n" if $DEBUG;
55 my $response = $ua->get($url);
56 if ( ! $response->is_success ) {
57 die $response->status_line;
59 write_file($file, $response->decoded_content);
62 system('unzip', $file);
63 $file =~ s/\.zip$/.csv/;
65 die "$file not found in zip archive.\n";
67 open my $fh, '<', $file
68 or die "couldn't open $file: $!\n";
69 my $csv = Text::CSV->new;
70 my $header = $csv->getline($fh);
71 $csv->column_names(@$header);
72 # columns we care about are headed 'Code' and 'Rate'
74 my $total_changed = 0;
75 my $total_skipped = 0;
76 while ( !$csv->eof ) {
77 my $line = $csv->getline_hr($fh);
78 my $district = $line->{Code} or next;
79 $district = sprintf('%04d', $district);
80 my $tax = sprintf('%.1f', $line->{Rate} * 100);
83 # find rate(s) in this country+state+district+taxclass that have the
84 # wa_sales flag and the configured taxname, and haven't been disabled.
85 my @rates = qsearch('cust_main_county', {
87 state => 'WA', # this is specific to WA
88 district => $district,
91 tax => { op => '>', value => '0' },
93 foreach my $rate (@rates) {
94 if ( $rate->tax == $tax ) {
97 $rate->set('tax', $tax);
98 my $error = $rate->replace;
99 die "error updating district $district: $error\n" if $error;
102 } # foreach $taxclass
103 print "$district: updated $changed, skipped $skipped\n"
104 if $DEBUG and ($changed or $skipped);
105 $total_changed += $changed;
106 $total_skipped += $skipped;
108 print "Updated $total_changed tax rates.\nSkipped $total_skipped unchanged rates.\n" if $DEBUG;
110 } # else $method isn't wa_sales, no other methods exist yet