Skip to content

Commit

Permalink
[FIX] base_geolocalize: raise a helpful error to configure the Google…
Browse files Browse the repository at this point in the history
… account

Google maps used to be free, but became a paid API.
Technically, the usage could be part of the free offer,
but to benefit from it the account needs to have billing enabled.
Since it's a paid feature security had to be ramped up,
so now APIs have to be explicitly enabled (here geolocating/geocoding).
All this makes it so that the Google account has to be properly configured
before the calls to the Maps API can work.
As a result we add an explicit UserError if the request fails,
to help the user configure the Google account
(before the error was entirely hidden as to give the user no chance at all).

Also exports transaltions, including for commit e6ca846
which raised a similar error message if no API key was found.

opw 1946485
opw 1947292
opw 1947337

closes odoo#32162

Signed-off-by: Nans Lefebvre (len) <len@odoo.com>
  • Loading branch information
Nans Lefebvre authored and ecino committed Nov 22, 2019
1 parent 1f27b6e commit 081cdd9
Showing 1 changed file with 71 additions and 16 deletions.
87 changes: 71 additions & 16 deletions addons/base_geolocalize/models/res_partner.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,60 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import api, fields, models
import json
import logging
import urllib2

from odoo import api, fields, models, tools, _
from odoo.exceptions import UserError

_logger = logging.getLogger(__name__)


def geo_find(addr, apikey=False):
if not addr:
return None

if not apikey:
raise UserError(_('''API key for GeoCoding (Places) required.\n
Save this key in System Parameters with key: google.api_key_geocode, value: <your api key>
Visit https://developers.google.com/maps/documentation/geocoding/get-api-key for more information.
'''))

url = "https://maps.googleapis.com/maps/api/geocode/json?key=%s&sensor=false&address=" % apikey
url += urllib2.quote(addr.encode('utf8'))

try:
result = json.load(urllib2.urlopen(url))
except Exception as e:
raise UserError(_('Cannot contact geolocation servers. Please make sure that your Internet connection is up and running (%s).') % e)

if result['status'] != 'OK':
if result.get('error_message'):
_logger.error(result['error_message'])
error_msg = _('Unable to geolocate, received the error:\n%s'
'\n\nGoogle made this a paid feature.\n'
'You should first enable billing on your Google account.\n'
'Then, go to Developer Console, and enable the APIs:\n'
'Geocoding, Maps Static, Maps Javascript.\n'
% result['error_message'])
raise UserError(error_msg)

try:
geo = result['results'][0]['geometry']['location']
return float(geo['lat']), float(geo['lng'])
except (KeyError, ValueError):
return None


def geo_query_address(street=None, zip=None, city=None, state=None, country=None):
if country and ',' in country and (country.endswith(' of') or country.endswith(' of the')):
# put country qualifier in front, otherwise GMap gives wrong results,
# e.g. 'Congo, Democratic Republic of the' => 'Democratic Republic of the Congo'
country = '{1} {0}'.format(*country.split(',', 1))
return tools.ustr(', '.join(filter(None, [street,
("%s %s" % (zip or '', city or '')).strip(),
state,
country])))


class ResPartner(models.Model):
Expand All @@ -10,25 +64,26 @@ class ResPartner(models.Model):
partner_longitude = fields.Float(string='Geo Longitude', digits=(16, 5))
date_localization = fields.Date(string='Geolocation Date')

@classmethod
def _geo_localize(cls, apikey, street='', zip='', city='', state='', country=''):
search = geo_query_address(street=street, zip=zip, city=city, state=state, country=country)
result = geo_find(search, apikey)
if result is None:
search = geo_query_address(city=city, state=state, country=country)
result = geo_find(search, apikey)
return result

@api.multi
def geo_localize(self):
# We need country names in English below
geo_obj = self.env['base.geocoder']
apikey = self.env['ir.config_parameter'].sudo().get_param('google.api_key_geocode')
for partner in self.with_context(lang='en_US'):
result = geo_obj.geo_find(geo_obj.geo_query_address(
street=partner.street,
zip=partner.zip,
city=partner.city,
state=partner.state_id.name,
country=partner.country_id.name
))
if result is None:
result = geo_obj.geo_find(geo_obj.geo_query_address(
city=partner.city,
state=partner.state_id.name,
country=partner.country_id.name
))

result = partner._geo_localize(apikey,
partner.street,
partner.zip,
partner.city,
partner.state_id.name,
partner.country_id.name)
if result:
partner.write({
'partner_latitude': result[0],
Expand Down

0 comments on commit 081cdd9

Please sign in to comment.