CCH taxes with new customer locations, #21485
authorMark Wells <mark@freeside.biz>
Sat, 24 Aug 2013 22:43:08 +0000 (15:43 -0700)
committerMark Wells <mark@freeside.biz>
Sat, 24 Aug 2013 22:43:08 +0000 (15:43 -0700)
FS/FS/cust_main/Billing.pm
FS/FS/cust_main/Location.pm
FS/FS/cust_main/Search.pm
FS/FS/geocode_Mixin.pm
FS/FS/tax_rate.pm
bin/test_scrub
httemplate/elements/standardize_locations.js
httemplate/misc/confirm-address_standardize.html

index 081dd70..0a364f5 100644 (file)
@@ -1387,6 +1387,8 @@ sub _handle_taxes {
 
   local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG;
 
+  my $location = $cust_pkg->tax_location;
+
   return if ( $self->payby eq 'COMP' ); #dubious
 
   if ( $conf->exists('enable_taxproducts')
@@ -1429,7 +1431,7 @@ sub _handle_taxes {
 
     }
 
-    my %tax_cust_bill_pkg = $cust_bill_pkg->disintegrate;
+    my %tax_cust_bill_pkg = $cust_bill_pkg->disintegrate; # grrr
     foreach my $key (keys %tax_cust_bill_pkg) {
       # $key is "setup", "recur", or a usage class name. ('' is a usage class.)
       # $tax_cust_bill_pkg{$key} is a cust_bill_pkg for that component of 
@@ -1444,11 +1446,6 @@ sub _handle_taxes {
 
         # this is the tax identifier, not the taxname
         my $taxname = ref( $tax ). ' '. $tax->taxnum;
-        $taxname .= ' billpkgnum'. $cust_bill_pkg->billpkgnum;
-        # We need to create a separate $taxlisthash entry for each billpkgnum
-        # on the invoice, so that cust_bill_pkg_tax_location records will
-        # be linked correctly.
-
         # $taxlisthash: keys are "setup", "recur", and usage classes.
         # Values are arrayrefs, first the tax object (cust_main_county
         # or tax_rate) and then any cust_bill_pkg objects that the 
@@ -1468,7 +1465,7 @@ sub _handle_taxes {
           if $DEBUG > 2;
         next unless $tax_object->can('tax_on_tax');
 
-        foreach my $tot ( $tax_object->tax_on_tax( $self ) ) {
+        foreach my $tot ( $tax_object->tax_on_tax( $location ) ) {
           my $totname = ref( $tot ). ' '. $tot->taxnum;
 
           warn "checking $totname which we call ". $tot->taxname. " as applicable\n"
@@ -1476,7 +1473,7 @@ sub _handle_taxes {
           next unless exists( $localtaxlisthash{ $totname } ); # only increase
                                                                # existing taxes
           warn "adding $totname to taxed taxes\n" if $DEBUG > 2;
-          # we're calling taxline() right here?  wtf?
+          # calculate the tax amount that the tax_on_tax will apply to
           my $hashref_or_error = 
             $tax_object->taxline( $localtaxlisthash{$tax},
                                   'custnum'      => $self->custnum,
@@ -1485,6 +1482,7 @@ sub _handle_taxes {
           return $hashref_or_error
             unless ref($hashref_or_error);
           
+          # and append it to the list of taxable items
           $taxlisthash->{ $totname } ||= [ $tot ];
           push @{ $taxlisthash->{ $totname  } }, $hashref_or_error->{amount};
 
@@ -1500,7 +1498,6 @@ sub _handle_taxes {
     # because we need to record that fact.
 
     my @loc_keys = qw( district city county state country );
-    my $location = $cust_pkg->tax_location;
     my %taxhash = map { $_ => $location->$_ } @loc_keys;
 
     $taxhash{'taxclass'} = $part_pkg->taxclass;
@@ -1544,12 +1541,7 @@ sub _gather_taxes {
 
   local($DEBUG) = $FS::cust_main::DEBUG if $FS::cust_main::DEBUG > $DEBUG;
 
-  my $geocode;
-  if ( $cust_pkg->locationnum && $conf->exists('tax-pkg_address') ) {
-    $geocode = $cust_pkg->cust_location->geocode('cch');
-  } else {
-    $geocode = $self->geocode('cch');
-  }
+  my $geocode = $cust_pkg->tax_location->geocode('cch');
 
   my @taxes = ();
 
index 22feaf9..5590f88 100644 (file)
@@ -124,6 +124,11 @@ sub _upgrade_data {
   local $DEBUG = 0;
   my $error;
 
+  my $tax_prefix = 'bill_';
+  if ( FS::Conf->new->exists('tax-ship_address') ) {
+    $tax_prefix = 'ship_';
+  }
+
   # Step 0: set up contact classes and phone types
   my $service_contact_class = 
     qsearchs('contact_class', { classname => 'Service'})
@@ -198,6 +203,14 @@ sub _upgrade_data {
           'last'        => $cust_main->get('ship_last'),
           'first'       => $cust_main->get('ship_first'),
         });
+        if ( !$cust_main->get('ship_last') or !$cust_main->get('ship_first') )
+        {
+          warn "customer $custnum has no service contact name; substituting ".
+               "customer name\n";
+          $contact->set('last' => $cust_main->get('last'));
+          $contact->set('first' => $cust_main->get('first'));
+        }
+
         if ( $unlike{'company'} ) {
           # there's no contact.company field, but keep a record of it
           $contact->set(comment => 'Company: '.$cust_main->get('ship_company'));
@@ -224,6 +237,20 @@ sub _upgrade_data {
         $cust_main->set("ship_$_" => '') foreach qw(last first company);
       } #if %unlike
     } #if ship_address1
+
+    # special case: should go with whichever location is used to calculate
+    # taxes, because that's the one it originally came from
+    if ( my $geocode = $cust_main->get('geocode') ) {
+      $bill_location->set('geocode' => '');
+      $ship_location->set('geocode' => '');
+
+      if ( $tax_prefix eq 'bill_' ) {
+        $bill_location->set('geocode', $geocode);
+      } elsif ( $tax_prefix eq 'ship_' ) {
+        $ship_location->set('geocode', $geocode);
+      }
+    }
+
     $error = $bill_location->insert;
     die "error migrating billing address for customer $custnum: $error"
       if $error;
index b022985..f14f897 100644 (file)
@@ -668,7 +668,9 @@ sub search {
   # parse with hardcoded tax location checkbox
   ##
 
-  push @where, "ship_location.geocode is not null"
+  my $tax_prefix = FS::Conf->new->exists('tax-ship_location') ? 'ship_' 
+                                                              : 'bill_';
+  push @where, "${tax_prefix}location.geocode is not null"
     if $params->{'with_geocode'};
 
   ##
index 29491db..57d8ca0 100644 (file)
@@ -186,12 +186,17 @@ sub geocode {
   my $geocode = $self->get('geocode');  #XXX only one data_vendor for geocode
   return $geocode if $geocode;
 
-  my $prefix =
-   ( FS::Conf->new->exists('tax-ship_address') && $self->has_ship_address )
-   ? 'ship_'
-   : '';
+  if ( $self->isa('FS::cust_main') ) {
+    warn "WARNING: FS::cust_main->geocode deprecated";
+
+    # do the best we can
+    my $m = FS::Conf->new->exists('tax-ship_address') ? 'ship_location'
+                                                      : 'bill_location';
+    my $location = $self->$m or return '';
+    return $location->geocode($data_vendor);
+  }
 
-  my($zip,$plus4) = split /-/, $self->get("${prefix}zip")
+  my($zip,$plus4) = split /-/, $self->get('zip')
     if $self->country eq 'US';
 
   $zip ||= '';
@@ -212,7 +217,7 @@ sub geocode {
     if scalar(@cust_tax_location);
 
   warn "WARNING: customer ". $self->custnum.
-       ": multiple locations for zip ". $self->get("${prefix}zip").
+       ": multiple locations for zip ". $self->get("zip").
        "; using arbitrary geocode $geocode\n"
     if scalar(@cust_tax_location) > 1;
 
index 342c7cb..095939f 100644 (file)
@@ -514,10 +514,10 @@ sub _fatal_or_null {
   }
 }
 
-=item tax_on_tax CUST_MAIN
+=item tax_on_tax CUST_LOCATION
 
 Returns a list of taxes which are candidates for taxing taxes for the
-given customer (see L<FS::cust_main>)
+given service location (see L<FS::cust_location>)
 
 =cut
 
@@ -525,13 +525,13 @@ given customer (see L<FS::cust_main>)
 sub tax_on_tax {
        #akshun
   my $self = shift;
-  my $cust_main = shift;
+  my $cust_location = shift;
 
   warn "looking up taxes on tax ". $self->taxnum. " for customer ".
-    $cust_main->custnum
+    $cust_location->custnum
     if $DEBUG;
 
-  my $geocode = $cust_main->geocode($self->data_vendor);
+  my $geocode = $cust_location->geocode($self->data_vendor);
 
   # CCH oddness in m2m
   my $dbh = dbh;
@@ -2120,8 +2120,7 @@ EOF
 
 =head1 SEE ALSO
 
-L<FS::Record>, L<FS::cust_main>, L<FS::cust_bill>, schema.html from the base
-documentation.
+L<FS::Record>, L<FS::cust_location>, L<FS::cust_bill>
 
 =cut
 
index 88edc33..45a257a 100644 (file)
@@ -42,10 +42,17 @@ my $dsth = dbh->prepare("DELETE FROM cust_main_invoice WHERE dest != 'POST'")
   or die dbh->errstr;
 $dsth->execute or die $dsth->errstr;
 
+my $sth = dbh->prepare("UPDATE part_event SET disabled = 'Y'");
+$sth->execute or die $sth->errstr;
+
 my $conf = new FS::Conf;
 foreach my $item (qw(
   business-onlinepayment
   business-onlinepayment-ach
+  dump-localdest
+  dump-scpdest
+  cust_bill-ftp_spool
+  smtpmachine
 )) {
   $conf->delete($item);
 }
index d7c3670..ad774d8 100644 (file)
@@ -207,7 +207,7 @@ function post_standardization() {
 
     var country_el = cf.elements['<% $taxpre %>country'];
     var country = country_el.options[ country_el.selectedIndex ].value;
-    var geocode = cf.elements['bill_geocode'].value;
+    var geocode = cf.elements['<% $taxpre %>geocode'].value;
 
     if ( country == 'CA' || country == 'US' ) {
 
@@ -229,14 +229,14 @@ function post_standardization() {
 
     } else {
 
-      cf.elements['bill_geocode'].value = 'DEFAULT';
+      cf.elements['<% $taxpre %>geocode'].value = 'DEFAULT';
       <% $post_geocode %>;
 
     }
 
   } else {
 
-    cf.elements['bill_geocode'].value = '';
+    cf.elements['<% $taxpre %>geocode'].value = '';
     <% $post_geocode %>;
 
   }
@@ -261,7 +261,7 @@ function update_geocode() {
     cf.elements['<% $taxpre %>city'].value     = argsHash['city'];
     setselect(cf.elements['<% $taxpre %>state'], argsHash['state']);
     cf.elements['<% $taxpre %>zip'].value      = argsHash['zip'];
-    cf.elements['bill_geocode'].value  = argsHash['geocode'];
+    cf.elements['<% $taxpre %>geocode'].value  = argsHash['geocode'];
     <% $post_geocode %>;
 
   }
index 420e8ea..33d2219 100644 (file)
@@ -103,7 +103,7 @@ Confirm address standardization
 % else {
   <TR>
     <TD ALIGN="center">
-    <BUTTON TYPE="button" STYLE="width:205px" onclick="confirm_manual_address()();">
+    <BUTTON TYPE="button" STYLE="width:205px" onclick="confirm_manual_address();">
       <IMG SRC="<%$p%>images/error.png" ALT=""> Use entered <%$addresses%>
     </BUTTON></TD>
     <TD ALIGN="center">