better detection of new locations that are the same as existing locations, #940,...
authorMark Wells <mark@freeside.biz>
Sat, 30 Mar 2013 06:15:21 +0000 (23:15 -0700)
committerMark Wells <mark@freeside.biz>
Sat, 30 Mar 2013 06:15:21 +0000 (23:15 -0700)
12 files changed:
FS/FS/cust_bill_pkg.pm
FS/FS/cust_location.pm
FS/FS/cust_main/Packages.pm
FS/FS/cust_pkg.pm
httemplate/edit/cust_location.cgi
httemplate/edit/process/change-cust_pkg.html
httemplate/edit/process/cust_location.cgi
httemplate/edit/process/cust_main.cgi
httemplate/edit/process/quick-cust_pkg.cgi
httemplate/edit/process/svc_phone.html
httemplate/elements/tr-select-cust_location.html
httemplate/misc/location.cgi

index 716c098..d8cbf59 100644 (file)
@@ -1104,8 +1104,7 @@ sub upgrade_tax_location {
     delete @hash{qw(censustract censusyear latitude longitude coord_auto)};
 
     $hash{custnum} = $h_cust_main->custnum;
-    my $tax_loc = qsearchs('cust_location', \%hash) # unlikely
-                  || FS::cust_location->new({ %hash });
+    my $tax_loc = FS::cust_location->new_or_existing(\%hash);
     if ( !$tax_loc->locationnum ) {
       $tax_loc->disabled('Y');
       my $error = $tax_loc->insert;
index b25163f..355bdb0 100644 (file)
@@ -5,7 +5,7 @@ use strict;
 use vars qw( $import );
 use Locale::Country;
 use FS::UID qw( dbh driver_name );
-use FS::Record qw( qsearch ); #qsearchs );
+use FS::Record qw( qsearch qsearchs );
 use FS::Conf;
 use FS::prospect_main;
 use FS::cust_main;
@@ -104,6 +104,31 @@ points to.  You can ask the object for a copy with the I<hash> method.
 
 sub table { 'cust_location'; }
 
+=item new_or_existing HASHREF
+
+Returns an existing location matching the customer and address fields in 
+HASHREF, if one exists; otherwise returns a new location containing those 
+fields.  The following fields must match: address1, address2, city, county,
+state, zip, country, geocode, disabled.  Other fields are only required
+to match if they're specified in HASHREF.
+
+The new location will not be inserted; the calling code must call C<insert>
+(or a method such as C<move_to>) to insert it, and check for errors at that
+point.
+
+=cut
+
+sub new_or_existing {
+  my $class = shift;
+  my %hash = ref($_[0]) ? %{$_[0]} : @_;
+  foreach ( qw(address1 address2 city county state zip country geocode
+              disabled ) ) {
+    # empty fields match only empty fields
+    $hash{$_} = '' if !defined($hash{$_});
+  }
+  return qsearchs('cust_location', \%hash) || $class->new(\%hash);
+}
+
 =item insert
 
 Adds this record to the database.  If there is an error, returns the error,
index 588f8a1..a3809f6 100644 (file)
@@ -100,17 +100,26 @@ sub order_pkg {
   local $FS::UID::AutoCommit = 0;
   my $dbh = dbh;
 
-  if ( $opt->{'cust_location'} &&
-       ( ! $cust_pkg->locationnum || $cust_pkg->locationnum == -1 ) ) {
-    my $error = $opt->{'cust_location'}->insert;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return "inserting cust_location (transaction rolled back): $error";
+  if ( $opt->{'locationnum'} and $opt->{'locationnum'} != -1 ) {
+
+    $cust_pkg->locationnum($opt->{'locationnum'});
+
+  } elsif ( $opt->{'cust_location'} ) {
+
+    if ( ! $opt->{'cust_location'}->locationnum ) {
+      # not inserted yet
+      my $error = $opt->{'cust_location'}->insert;
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "inserting cust_location (transaction rolled back): $error";
+      }
     }
     $cust_pkg->locationnum($opt->{'cust_location'}->locationnum);
-  }
-  else {
+
+  } else {
+
     $cust_pkg->locationnum($self->ship_locationnum);
+
   }
 
   $cust_pkg->custnum( $self->custnum );
index ed059d1..ab479dd 100644 (file)
@@ -1749,12 +1749,17 @@ sub change {
 
   if ( $opt->{'cust_location'} &&
        ( ! $opt->{'locationnum'} || $opt->{'locationnum'} == -1 ) ) {
-    $error = $opt->{'cust_location'}->insert;
-    if ( $error ) {
-      $dbh->rollback if $oldAutoCommit;
-      return "inserting cust_location (transaction rolled back): $error";
+
+    if ( ! $opt->{'cust_location'}->locationnum ) {
+      # not inserted yet
+      $error = $opt->{'cust_location'}->insert;
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "inserting cust_location (transaction rolled back): $error";
+      }
     }
     $opt->{'locationnum'} = $opt->{'cust_location'}->locationnum;
+
   }
 
   my $unused_credit = 0;
index a5e7d20..b90ba66 100755 (executable)
@@ -8,8 +8,12 @@ ACTION="<% $p %>edit/process/cust_location.cgi" METHOD=POST>
 
 <% ntable('#cccccc') %>
 <& /elements/location.html,
-            'object'        => $cust_location,
-            'no_asterisks'  => 1,
+  'object'              => $cust_location,
+  'no_asterisks'        => 1,
+  # these are service locations, so they need all this stuff
+  'enable_coords'       => 1,
+  'enable_district'     => 1,
+  'enable_censustract'  => 1,
 &>
 <& /elements/standardize_locations.html,
             'form'          => 'EditLocationForm',
index 2770f32..77f261d 100644 (file)
@@ -32,11 +32,11 @@ my %change = map { $_ => scalar($cgi->param($_)) }
 $change{'keep_dates'} = 1;
 
 if ( $cgi->param('locationnum') == -1 ) {
-  my $cust_location = new FS::cust_location {
+  my $cust_location = FS::cust_location->new_or_existing({
     'custnum' => $cust_pkg->custnum,
     map { $_ => scalar($cgi->param($_)) }
         qw( address1 address2 city county state zip country )
-  };
+  });
   $change{'cust_location'} = $cust_location;
 }
 
index b9f93db..56c3968 100644 (file)
@@ -28,11 +28,10 @@ my $cust_location = qsearchs({
 });
 die "unknown locationnum $locationnum" unless $cust_location;
 
-my $new = FS::cust_location->new({
+my $new = FS::cust_location->new_or_existing({
   custnum     => $cust_location->custnum,
   prospectnum => $cust_location->prospectnum,
-  map { $_ => scalar($cgi->param($_)) }
-    qw( address1 address2 city county state zip country )
+  map { $_ => scalar($cgi->param($_)) } FS::cust_main->location_fields
 });
 
 my $error = $cust_location->move_to($new);
index 054973f..c1f8155 100755 (executable)
@@ -83,10 +83,7 @@ for my $pre (qw(bill ship)) {
   }
   $hash{'custnum'} = $cgi->param('custnum');
   warn Dumper \%hash if $DEBUG;
-  # if we can qsearchs it, then it's unchanged, so use that
-  $locations{$pre} = qsearchs('cust_location', \%hash)
-                     || FS::cust_location->new( \%hash );
-
+  $locations{$pre} = FS::cust_location->new_or_existing(\%hash);
 }
 
 if ( ($cgi->param('same') || '') eq 'Y' ) {
index 2dadbcc..4ea4ace 100644 (file)
@@ -143,10 +143,10 @@ if ( $quotationnum ) {
   my %opt = ( 'cust_pkg' => $cust_pkg );
 
   if ( $locationnum == -1 ) {
-    my $cust_location = new FS::cust_location {
+    my $cust_location = FS::cust_location->new_or_existing({
       map { $_ => scalar($cgi->param($_)) }
-          qw( custnum address1 address2 city county state zip country geocode )
-    };
+          ('custnum', FS::cust_main->location_fields)
+    });
     $opt{'cust_location'} = $cust_location;
   }
 
index 27e9755..9983ea2 100644 (file)
@@ -40,10 +40,10 @@ my $args_callback = sub {
 
   my %opt = ();
   if ( $cgi->param('locationnum') == -1 ) {
-    my $cust_location = new FS::cust_location {
+    my $cust_location = FS::cust_location->new_or_existing({
       map { $_ => scalar($cgi->param($_)) }
           qw( custnum address1 address2 city county state zip country )
-    };
+    });
     $opt{'cust_location'} = $cust_location;
   }
 
index 7ffbd6c..4c17249 100644 (file)
@@ -153,25 +153,16 @@ Example:
     }
   }
 
+  var location_fields = <% to_json(\@location_fields) %>;
   function update_location( string ) {
-    var hash = eval('('+string+')');
-    document.getElementById('address1').value = hash['address1'];
-    document.getElementById('city').value     = hash['city'];
-    document.getElementById('zip').value      = hash['zip'];
-
-%   if ( $opt{'alt_format'} ) {
-      changeSelect( document.getElementById('location_kind'), hash['location_kind']);
-      changeSelect( document.getElementById('location_type'), hash['location_type']);
-      document.getElementById('location_number').value = hash['location_number'];
-%   } else {
-      document.getElementById('address2').value = hash['address2'];
-%   }
-
-    var country_el = document.getElementById('country');
-
-    changeSelect( country_el, hash['country'] );
-
-    country_changed( country_el,
+    var hash = JSON.parse(string);
+    for(var i = 0; i < location_fields.length; i++) {
+      var f = location_fields[i];
+      if (hash[f] && document.getElementById(f))  {
+        document.getElementById(f).value = hash[f];
+      }
+    }
+    country_changed( document.getElementById('country'),
                      fix_state_factory( hash['state'],
                                         hash['county']
                                       )
@@ -185,7 +176,7 @@ Example:
   <TD COLSPAN=7>
     <SELECT NAME     = "locationnum"
             ID       = "locationnum"
-            onChange = "locationnum_changed(this);"
+            onchange = "locationnum_changed(this);"
     >
 % if ( $cust_main ) {
       <OPTION VALUE="<% $cust_main->ship_locationnum %>"><% $opt{'empty_label'} || '(default service address)' |h %>
@@ -258,9 +249,7 @@ if ( $cgi->param('error') ) {
 my $editable = $cust_main ? 0 : 1; #could use explicit control
 my $addnew = $cust_main ? 1 : ( $locationnum>0 ? 0 : 1 );
 
-my @location_fields = qw( address1 address2 city county state zip country
-                          latitude longitude
-                        );
+my @location_fields = FS::cust_main->location_fields;
 if ( $opt{'alt_format'} ) {
     push @location_fields, qw( location_type location_number location_kind );
 }
index 188c5c3..35ae0f1 100644 (file)
@@ -24,8 +24,9 @@ my $cust_location = qsearchs({
 
 my %hash = ();
 %hash = map { $_ => $cust_location->$_() }
-            qw( address1 address2 city county state zip country
-                location_kind location_type location_number )
+            ( FS::cust_main->location_fields,
+              qw( location_kind location_type location_number )
+            )
   if $cust_location;
 
 </%init>