"on hold" package ordering and status, RT#28508
[freeside.git] / FS / FS / cust_main / Location.pm
index 5590f88..9899f72 100644 (file)
@@ -4,6 +4,7 @@ use strict;
 use vars qw( $DEBUG $me @location_fields );
 use FS::Record qw(qsearch qsearchs);
 use FS::UID qw(dbh);
+use FS::Cursor;
 use FS::cust_location;
 
 use Carp qw(carp);
@@ -24,11 +25,13 @@ BEGIN {
     foreach my $f (@location_fields) {
       *{"FS::cust_main::Location::$f"} = sub {
         carp "WARNING: tried to set cust_main.$f with accessor" if (@_ > 1);
-        shift->bill_location->$f
+        my $l = shift->bill_location;
+        $l ? $l->$f : '';
       };
       *{"FS::cust_main::Location::ship_$f"} = sub {
         carp "WARNING: tried to set cust_main.ship_$f with accessor" if (@_ > 1);
-        shift->ship_location->$f
+        my $l = shift->ship_location;
+        $l ? $l->$f : '';
       };
     }
     $init++;
@@ -135,6 +138,7 @@ sub _upgrade_data {
     || new FS::contact_class { classname => 'Service'};
 
   if ( !$service_contact_class->classnum ) {
+    warn "Creating service contact class.\n";
     $error = $service_contact_class->insert;
     die "error creating contact class for Service: $error" if $error;
   }
@@ -156,7 +160,12 @@ sub _upgrade_data {
     }
   }
 
-  foreach my $cust_main (qsearch('cust_main', { bill_locationnum => '' })) {
+  warn "Migrating customer locations.\n";
+  my $search = FS::Cursor->new('cust_main',
+                        { bill_locationnum  => '',
+                          address1          => { op=>'!=', value=>'' }
+                        });
+  while (my $cust_main = $search->fetch) {
     # Step 1: extract billing and service addresses into cust_location
     my $custnum = $cust_main->custnum;
     my $bill_location = FS::cust_location->new(
@@ -165,7 +174,10 @@ sub _upgrade_data {
         map { $_ => $cust_main->get($_) } location_fields(),
       }
     );
-    $bill_location->set('censustract', ''); # properly goes with ship_location
+    $bill_location->set('censustract', '');
+    $bill_location->set('censusyear', '');
+     # properly goes with ship_location; if they're the same, will be set
+     # on ship_location before inserting either one
     my $ship_location = $bill_location; # until proven otherwise
 
     if ( $cust_main->get('ship_address1') ) {
@@ -187,8 +199,6 @@ sub _upgrade_data {
         );
       } # else it stays equal to $bill_location
 
-      $ship_location->set('censustract', $cust_main->get('censustract'));
-
       # Step 2: Extract shipping address contact fields into contact
       my %unlike = map { $_ => 1 }
         grep { $cust_main->get($_) ne $cust_main->get("ship_$_") }
@@ -251,6 +261,11 @@ sub _upgrade_data {
       }
     }
 
+    # this always goes with the ship_location (whether it's the same as
+    # bill_location or not)
+    $ship_location->set('censustract', $cust_main->get('censustract'));
+    $ship_location->set('censusyear',  $cust_main->get('censusyear'));
+
     $error = $bill_location->insert;
     die "error migrating billing address for customer $custnum: $error"
       if $error;
@@ -275,9 +290,9 @@ sub _upgrade_data {
       if $error;
 
     # Step 4: set packages at the "default service location" to ship_location
-    foreach my $cust_pkg (
-      qsearch('cust_pkg', { custnum => $custnum, locationnum => '' })  
-    ) {
+    my $pkg_search =
+      FS::Cursor->new('cust_pkg', { custnum => $custnum, locationnum => '' });
+    while (my $cust_pkg = $pkg_search->fetch) {
       # not a location change
       $cust_pkg->set('locationnum', $cust_main->ship_locationnum);
       $error = $cust_pkg->replace;
@@ -285,7 +300,39 @@ sub _upgrade_data {
         if $error;
     }
 
-  } #foreach $cust_main
+  } #while (my $cust_main...)
+
+  # repair an error in earlier upgrades
+  if (!FS::upgrade_journal->is_done('cust_location_censustract_repair')
+       and FS::Conf->new->exists('cust_main-require_censustract') ) {
+
+    foreach my $cust_location (
+      qsearch('cust_location', { 'censustract' => '' })
+    ) {
+      my $custnum = $cust_location->custnum;
+      next if !$custnum; # avoid doing this for prospect locations
+      my $address1 = $cust_location->address1;
+      # find the last history record that had that address
+      my $last_h = qsearchs({
+          table     => 'h_cust_main',
+          extra_sql => " WHERE custnum = $custnum AND address1 = ".
+                        dbh->quote($address1) .
+                        " AND censustract IS NOT NULL",
+          order_by  => " ORDER BY history_date DESC LIMIT 1",
+      });
+      if (!$last_h) {
+        # this is normal; just means it never had a census tract before
+        next;
+      }
+      $cust_location->set('censustract' => $last_h->get('censustract'));
+      $cust_location->set('censusyear'  => $last_h->get('censusyear'));
+      my $error = $cust_location->replace;
+      warn "Error setting census tract for customer #$custnum:\n  $error\n"
+        if $error;
+    } # foreach $cust_location
+    FS::upgrade_journal->set_done('cust_location_censustract_repair');
+  }
+
 }
 
 =back