- foreach my $from ('address1', 'address2') {
- foreach my $parse ( keys %parse ) {
- my $value = $self->get($prefix.$from);
- if ( $value =~ s/(^|\W+)$parse\W+(\w+)\W*$//i ) {
- $self->set($prefix.'location_type', $parse{$parse});
- $self->set($prefix.'location_number', $2);
- $self->set($prefix.$from, $value);
- return '';
+ my %hash = map { $_ => uc( $tax_info->{$_} ) }
+ qw( district city county state country );
+ $hash{'source'} = $method; # apply the update only to taxes we maintain
+
+ my @classes = FS::part_pkg_taxclass->taxclass_names;
+ my $taxname = $conf->config('tax_district_taxname');
+ # there must be exactly one cust_main_county for each district+taxclass.
+ # do NOT exclude taxes that are zero.
+
+ # mutex here so that concurrent queue jobs can't make duplicates.
+ FS::cust_main_county->lock_table;
+ foreach my $taxclass (@classes) {
+ my @existing = qsearch('cust_main_county', {
+ %hash,
+ 'taxclass' => $taxclass
+ });
+
+ if ( scalar(@existing) == 0 ) {
+
+ # then create one with the assigned tax name, and the tax rate from
+ # the lookup.
+ my $new = new FS::cust_main_county({
+ %hash,
+ 'taxclass' => $taxclass,
+ 'taxname' => $taxname,
+ 'tax' => $tax_info->{tax},
+ 'exempt_amount' => 0,
+ });
+ $log->info("creating tax rate for district ".$tax_info->{'district'});
+ $error = $new->insert;
+
+ } else {
+
+ my $to_update = $existing[0];
+ # if there's somehow more than one, find the best candidate to be
+ # updated:
+ # - prefer tax > 0 over tax = 0 (leave disabled records disabled)
+ # - then, prefer taxname = the designated taxname
+ if ( scalar(@existing) > 1 ) {
+ $log->warning("tax district ".$tax_info->{district}." has multiple $method taxes.");
+ foreach (@existing) {
+ if ( $to_update->tax == 0 ) {
+ if ( $_->tax > 0 and $to_update->tax == 0 ) {
+ $to_update = $_;
+ } elsif ( $_->tax == 0 and $to_update->tax > 0 ) {
+ next;
+ } elsif ( $_->taxname eq $taxname and $to_update->tax ne $taxname ) {
+ $to_update = $_;
+ }
+ }
+ }
+ # don't remove the excess records here; upgrade does that.
+ }
+ my $taxnum = $to_update->taxnum;
+ if ( $to_update->tax == 0 ) {
+ $log->debug("tax#$taxnum is set to zero; not updating.");
+ } elsif ( $to_update->tax == $tax_info->{tax} ) {
+ # do nothing, no need to update
+ } else {
+ $to_update->set('tax', $tax_info->{tax});
+ $log->info("updating tax#$taxnum with new rate ($tax_info->{tax}).");
+ $error = $to_update->replace;