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 if ($method eq 'wa_sales') {
44 # download the update file
45 my $now = DateTime->now;
47 my $qt = $now->quarter;
48 my $file = "Rates${yr}Q${qt}.zip";
49 my $url = 'http://dor.wa.gov/downloads/Add_Data/'.$file;
52 my $ua = LWP::UserAgent->new;
53 warn "Downloading $url...\n" if $DEBUG;
54 my $response = $ua->get($url);
55 if ( ! $response->is_success ) {
56 die $response->status_line;
58 write_file($file, $response->decoded_content);
61 system('unzip', $file);
62 $file =~ s/\.zip$/.csv/;
64 die "$file not found in zip archive.\n";
66 open my $fh, '<', $file
67 or die "couldn't open $file: $!\n";
68 my $csv = Text::CSV->new;
69 my $header = $csv->getline($fh);
70 $csv->column_names(@$header);
71 # columns we care about are headed 'Code' and 'Rate'
73 my $total_changed = 0;
74 my $total_skipped = 0;
75 while ( !$csv->eof ) {
76 my $line = $csv->getline_hr($fh);
77 my $district = $line->{Code} or next;
78 $district = sprintf('%04d', $district);
79 my $tax = sprintf('%.1f', $line->{Rate} * 100);
82 # find rate(s) in this country+state+district+taxclass that have the
83 # wa_sales flag and the configured taxname, and haven't been disabled.
84 my @rates = qsearch('cust_main_county', {
86 state => 'WA', # this is specific to WA
87 district => $district,
90 tax => { op => '>', value => '0' },
92 foreach my $rate (@rates) {
93 if ( $rate->tax == $tax ) {
96 $rate->set('tax', $tax);
97 my $error = $rate->replace;
98 die "error updating district $district: $error\n" if $error;
101 } # foreach $taxclass
102 print "$district: updated $changed, skipped $skipped\n"
103 if $DEBUG and ($changed or $skipped);
104 $total_changed += $changed;
105 $total_skipped += $skipped;
107 print "Updated $total_changed tax rates.\nSkipped $total_skipped unchanged rates.\n" if $DEBUG;
109 } # else $method isn't wa_sales, no other methods exist yet