summaryrefslogtreecommitdiff
path: root/FS/FS/Cron/tax_rate_update.pm
blob: b6ac63c2efddfcde8dca249f46eb09ba8b577142 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/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') || '';

  FS::cust_main_county->lock_table;
  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
  '';
}

1;