summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Burger <burgerc@freeside.biz>2018-12-02 13:27:55 -0500
committerChristopher Burger <burgerc@freeside.biz>2018-12-02 13:27:55 -0500
commit7a24befdb65751f552247abf42df94276bcfa12f (patch)
treeb472bec032b49d18556d293e6b76a79d5b5d5fce
parentc955fc16406c0666bcfb6f3a5c27a2922bd9ec31 (diff)
parenta89510408116054d258baa026d9c2a4048644e4c (diff)
Merge branch 'FREESIDE_4_BRANCH' of ssh://git.freeside.biz/home/git/freeside into FREESIDE_4_BRANCH
-rw-r--r--FS/FS/Template_Mixin.pm22
-rw-r--r--FS/FS/geocode_Mixin.pm80
2 files changed, 81 insertions, 21 deletions
diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm
index ba36d9ef2..2b518d9d7 100644
--- a/FS/FS/Template_Mixin.pm
+++ b/FS/FS/Template_Mixin.pm
@@ -26,6 +26,7 @@ use FS::pkg_category;
use FS::pkg_class;
use FS::invoice_mode;
use FS::L10N;
+use FS::Log;
$DEBUG = 0;
$me = '[FS::Template_Mixin]';
@@ -3462,6 +3463,27 @@ sub _items_cust_bill_pkg {
if $DEBUG > 1;
my $cust_pkg = $cust_bill_pkg->cust_pkg;
+
+ unless ( $cust_pkg ) {
+ # There is no related row in cust_pkg for this cust_bill_pkg.pkgnum.
+ # This invoice may have been broken by an unusual combination
+ # of manually editing package dates, and aborted package changes
+ # when the manually edited dates used are nonsensical.
+
+ my $error = sprintf
+ 'cust_bill_pkg(billpkgnum:%s) '.
+ 'is missing related row in cust_pkg(pkgnum:%s)! '.
+ 'cust_bill(invnum:%s) is corrupted by bad database data, '.
+ 'and should be investigated',
+ $cust_bill_pkg->billpkgnum,
+ $cust_bill_pkg->pkgnum,
+ $cust_bill_pkg->invnum;
+
+ FS::Log->new('FS::cust_bill_pkg')->critical( $error );
+ warn $error;
+ next;
+ }
+
my $part_pkg = $cust_pkg->part_pkg;
# which pkgpart to show for display purposes?
diff --git a/FS/FS/geocode_Mixin.pm b/FS/FS/geocode_Mixin.pm
index b999be0ab..87ad9acfd 100644
--- a/FS/FS/geocode_Mixin.pm
+++ b/FS/FS/geocode_Mixin.pm
@@ -3,8 +3,11 @@ package FS::geocode_Mixin;
use strict;
use vars qw( $DEBUG $me );
use Carp;
+use Cpanel::JSON::XS;
+use Data::Dumper;
use Locale::Country ();
-use Geo::Coder::Googlev3; #compile time for now, until others are supported
+use LWP::UserAgent;
+use URI::Escape;
use FS::Record qw( qsearchs qsearch );
use FS::Conf;
use FS::cust_pkg;
@@ -163,31 +166,66 @@ API and set the 'latitude' and 'longitude' fields accordingly.
sub set_coord {
my $self = shift;
- #my $module = FS::Conf->new->config('geocode_module') || 'Geo::Coder::Googlev3';
-
- my $geocoder = Geo::Coder::Googlev3->new;
-
- my $location = eval {
- $geocoder->geocode( location =>
- $self->get('address1'). ','.
- ( $self->get('address2') ? $self->get('address2').',' : '' ).
- $self->get('city'). ','.
- $self->get('state'). ','.
- $self->country_full
- );
- };
- if ( $@ ) {
- warn "geocoding error: $@\n";
+ # Google documetnation:
+ # https://developers.google.com/maps/documentation/geocoding/start
+
+
+ my $api_key = FS::Conf->new->config('google_maps_api_key');
+
+ unless ( $api_key ) {
+ # Google API now requires a valid key with a payment method attached
+ warn 'Geocoding unavailable, install a google_maps_api_key';
return;
}
- my $geo_loc = $location->{'geometry'}{'location'} or return;
- if ( $geo_loc->{'lat'} && $geo_loc->{'lng'} ) {
- $self->set('latitude', $geo_loc->{'lat'} );
- $self->set('longitude', $geo_loc->{'lng'} );
- $self->set('coord_auto', 'Y');
+ my $google_api_url = 'https://maps.googleapis.com/maps/api/geocode/json';
+
+ my $address =
+ join ',',
+ map { $self->$_ ? uri_escape( $self->get( $_ ) ) : () }
+ qw( address1 address2 city state zip country_full );
+
+ my $query_url = sprintf
+ '%s?address=%s&key=%s',
+ $google_api_url, $address, $api_key;
+
+ my $ua = LWP::UserAgent->new;
+ $ua->timeout(10);
+ my $res = $ua->get( $query_url );
+ my $json_res = decode_json( $res->decoded_content );
+ my $json_error = $json_res->{error_message}
+ if ref $json_res && $json_res->{error_message};
+
+ if ( $DEBUG ) {
+ warn "\$query_url: $query_url\n";
+ warn "\$json_error: $json_error\n";
+ warn Dumper( $json_res || $res->decoded_content )."\n";
}
+ if ( !$res->is_success || $json_error ) {
+ warn "Error using google GeoCoding API";
+ warn Dumper( $json_res || $res->decoded_content );
+ return;
+ }
+
+ if (
+ ref $json_res
+ && ref $json_res->{results}
+ && ref $json_res->{results}->[0]
+ && ref $json_res->{results}->[0]->{geometry}
+ && ref $json_res->{results}->[0]->{geometry}->{location}
+ ) {
+ my $location = $json_res->{results}->[0]->{geometry}->{location};
+ if ( $location->{lat} && $location->{lng} ) {
+ $self->set( latitude => $location->{lat} );
+ $self->set( longitude => $location->{lng} );
+ $self->set( coord_auto => 'Y' );
+ }
+ } else {
+ # If google changes the API response structure, warnings abound
+ warn "No location match found using google GeoCoding API for $address";
+ warn Dumper( $json_res || $res->decoded_content );
+ }
}
=item geocode DATA_VENDOR