X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main%2FLocation.pm;h=9899f7230b9c5cc3469a1453d65f4ca1d4d6b610;hb=a7d8494c57376bfc493fbaa234b250cc86a79a94;hp=d1d6d67ffad1c25768e3fd0c1bf739b9d9b69d85;hpb=01629c3c934f1f6fd2ab9de5f7638f671fd59791;p=freeside.git diff --git a/FS/FS/cust_main/Location.pm b/FS/FS/cust_main/Location.pm index d1d6d67ff..9899f7230 100644 --- a/FS/FS/cust_main/Location.pm +++ b/FS/FS/cust_main/Location.pm @@ -4,11 +4,12 @@ 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); -$DEBUG = 1; +$DEBUG = 0; $me = '[FS::cust_main::Location]'; my $init = 0; @@ -18,16 +19,19 @@ BEGIN { no strict 'refs'; @location_fields = qw( address1 address2 city county state zip country district - latitude longitude coord_auto censustract censusyear geocode ); + latitude longitude coord_auto censustract censusyear geocode + addr_clean ); 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++; @@ -123,12 +127,18 @@ 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'}) || 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; } @@ -146,37 +156,48 @@ sub _upgrade_data { # just in case someone still doesn't have these if ( !$phone_type{$_}->phonetypenum ) { $error = $phone_type{$_}->insert; - die "error creating phone type '$_': $error"; + die "error creating phone type '$_': $error" if $error; } } - 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( { custnum => $custnum, - map { $_ => $cust_main->get($_) } location_fields() + map { $_ => $cust_main->get($_) } location_fields(), } ); - $error = $bill_location->insert; - die "error migrating billing address for customer $custnum: $error" - if $error; - - $cust_main->set(bill_locationnum => $bill_location->locationnum); + $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') ) { - my $ship_location = FS::cust_location->new( - { - custnum => $custnum, - map { $_ => $cust_main->get("ship_$_") } location_fields() + # detect duplicates + my $same = 1; + foreach (location_fields()) { + if ( length($cust_main->get("ship_$_")) and + $cust_main->get($_) ne $cust_main->get("ship_$_") ) { + $same = 0; } - ); - $error = $ship_location->insert; - die "error migrating service address for customer $custnum: $error" - if $error; + } - $cust_main->set(ship_locationnum => $ship_location->locationnum); + if ( !$same ) { + $ship_location = FS::cust_location->new( + { + custnum => $custnum, + map { $_ => $cust_main->get("ship_$_") } location_fields() + } + ); + } # else it stays equal to $bill_location # Step 2: Extract shipping address contact fields into contact my %unlike = map { $_ => 1 } @@ -192,6 +213,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')); @@ -218,10 +247,39 @@ sub _upgrade_data { $cust_main->set("ship_$_" => '') foreach qw(last first company); } #if %unlike } #if ship_address1 - else { - $cust_main->set(ship_locationnum => $bill_location->locationnum); + + # 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); + } } + # 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; + + $cust_main->set(bill_locationnum => $bill_location->locationnum); + + if (!$ship_location->locationnum) { + $error = $ship_location->insert; + die "error migrating service address for customer $custnum: $error" + if $error; + } + + $cust_main->set(ship_locationnum => $ship_location->locationnum); + # Step 3: Wipe the migrated fields and update the cust_main $cust_main->set("ship_$_" => '') foreach location_fields(); @@ -232,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; @@ -242,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