Browse Source

[IMP] partner_external_map: Better layout + icon + some refactoring

pull/237/head
Pedro M. Baeza 9 years ago
parent
commit
c5b4911c2d
  1. 42
      partner_external_map/README.rst
  2. 4
      partner_external_map/__init__.py
  3. 16
      partner_external_map/__openerp__.py
  4. 14
      partner_external_map/data/map_website_data.xml
  5. 33
      partner_external_map/hooks.py
  6. 5
      partner_external_map/models/__init__.py
  7. 30
      partner_external_map/models/map_website.py
  8. 109
      partner_external_map/models/res_partner.py
  9. 42
      partner_external_map/models/res_users.py
  10. 193
      partner_external_map/partner_external_maps.py
  11. 11
      partner_external_map/post_install.py
  12. BIN
      partner_external_map/static/description/icon.png
  13. 2887
      partner_external_map/static/description/icon.svg
  14. 0
      partner_external_map/views/map_website_view.xml
  15. 0
      partner_external_map/views/res_partner_view.xml
  16. 0
      partner_external_map/views/res_users_view.xml

42
partner_external_map/README.rst

@ -6,47 +6,52 @@
Partner External Maps
=====================
In the old days of Odoo/OpenERP, back in version 6.1, there was an official *google_map* module ; this module added a *Map* button on the partner form view and, when the user clicked on that button, it would open a new tab on its web browser and go to Google Map with a search on the address of the partner.
In the old days of Odoo/OpenERP, back in version 6.1, there was an official
*google_map* module ; this module added a *Map* button on the partner form view
and, when the user clicked on that button, it would open a new tab on its web
browser and go to Google Map with a search on the address of the partner.
This module aims at restoring this feature with several improvements:
* each user can select the map website he wants to use in its preferences
* there are now two buttons on the partner form view: one to open a regular map on the address of the partner, and another one to open an itinerary map from the start address configured in the preferences of the user to the address of the partner.
* Each user can select the map website he wants to use in its preferences
* There are now two buttons on the partner form view: one to open a regular map
on the address of the partner, and another one to open an itinerary map from
the start address configured in the preferences of the user to the address of
the partner.
This module supports several map websites:
* `Google Maps <https://www.google.com/maps>`
* `OpenStreetMap <https://www.openstreetmap.org/>`
* `Bing Maps <https://www.bing.com/maps/>`
* `Here Maps <https://www.here.com/>`
* `MapQuest <http://www.mapquest.com/>`
* `Yahoo! Maps <https://maps.yahoo.com/>`
If the module *base_geolocalize* from the official addons is installed on the system, it will use the latitude and longitude to localize the partner (instead of the address) if this information is present on the partner.
If the module *base_geolocalize* from the official addons is installed on the
system, it will use the latitude and longitude to localize the partner (instead
of the address) if this information is present on the partner.
Configuration
=============
If you want to create additionnal map websites, go to the menu *Sales > Configuration > Address Book > Localization > Map Websites*. You are invited to send the configuration information of your additionnal map websites to the author of the module, so that the module can be updated with more pre-configured map websites.
If you want to create additionnal map websites, go to the menu
*Sales > Configuration > Address Book > Localization > Map Websites*. You are
invited to send the configuration information of your additionnal map websites
to the author of the module, so that the module can be updated with more
pre-configured map websites.
Usage
=====
First, you need to configure in your preferences:
* the map website to use for the regular maps,
* the map website to use for the route maps,
* the start address for the route maps.
* The map website to use for the regular maps,
* The map website to use for the route maps,
* The start address for the route maps.
Then you can use the two new buttons on the partner form to open a regular map or a route map.
Then you can use the two new buttons on the partner form to open a regular map
or a route map.
.. image:: https://odoo-community.org/website/image/ir.attachment/5784_f2813bd/datas
:alt: Try me on Runbot
@ -61,7 +66,7 @@ check there if your issue has already been reported. If you spotted it first,
help us smashing it by providing a detailed and welcomed `feedback
<https://github.com/OCA/
partner-contact/issues/new?body=module:%20
partner_external_maps%0Aversion:%20
partner_external_map%0Aversion:%20
9.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Credits
@ -71,6 +76,7 @@ Contributors
------------
* Alexis de Lattre <alexis.delattre@akretion.com>
* Pedro M. Baeza <pedro.baeza@tecnativa.com>
Maintainer
----------

4
partner_external_map/__init__.py

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*-
from . import partner_external_maps
from .post_install import set_default_map_settings
from . import models
from .hooks import set_default_map_settings

16
partner_external_map/__openerp__.py

@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
# © 2015 Akretion (http://www.akretion.com)
# © 2015 Alexis de Lattre <alexis.delattre@akretion.com>
# © 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# @author Alexis de Lattre <alexis.delattre@akretion.com>
{
'name': 'Partner External Maps',
@ -10,14 +10,16 @@
'license': 'AGPL-3',
'summary': 'Add Map and Map Routing buttons on partner form to '
'open GMaps, OSM, Bing and others',
'author': 'Akretion,Odoo Community Association (OCA)',
'author': 'Akretion, '
'Tecnativa, '
'Odoo Community Association (OCA)',
'website': 'http://www.akretion.com',
'depends': ['base'],
'data': [
'partner_view.xml',
'map_website_data.xml',
'map_website_view.xml',
'users_view.xml',
'views/res_partner_view.xml',
'views/map_website_view.xml',
'data/map_website_data.xml',
'views/res_users_view.xml',
'security/ir.model.access.csv',
],
'post_init_hook': 'set_default_map_settings',

14
partner_external_map/map_website_data.xml → partner_external_map/data/map_website_data.xml

@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 Akretion (www.akretion.com)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
The licence is in the file __openerp__.py
-->
<!-- © 2015 Alexis de Lattre <alexis.delattre@akretion.com>
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). -->
<openerp>
<data>
<odoo>
<!-- Interesting source of information: http://northwestspatial.com/wp/?p=38 -->
<record id="google_maps" model="map.website">
@ -59,6 +55,4 @@
<field name="route_address_url">https://maps.yahoo.com/directions/?o={START_ADDRESS}&amp;d={DEST_ADDRESS}</field>
</record>
</data>
</openerp>
</odoo>

33
partner_external_map/hooks.py

@ -0,0 +1,33 @@
# -*- coding: utf-8 -*-
# © 2015 Alexis de Lattre <alexis.delattre@akretion.com>
# © 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import api, SUPERUSER_ID
import logging
logger = logging.getLogger(__name__)
def set_default_map_settings(cr, pool):
"""Method called as post-install script
The default method on the field can't be used, because it would be executed
before loading map_website_data.xml, so it would not be able to set a
value"""
with api.Environment.manage():
env = api.Environment(cr, SUPERUSER_ID, {})
user_model = env['res.users']
users = user_model.search([])
logger.info('Updating user settings for maps...')
users.write({
'context_map_website_id': user_model._default_map_website().id,
'context_route_map_website_id': (
user_model._default_route_map_website().id),
})
# Update the starting partner this way that is faster
cr.execute("""
UPDATE res_users
SET context_route_start_partner_id = partner_id
WHERE context_route_start_partner_id IS NULL;
""")

5
partner_external_map/models/__init__.py

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from . import map_website
from . import res_partner
from . import res_users

30
partner_external_map/models/map_website.py

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
# © 2015 Alexis de Lattre <alexis.delattre@akretion.com>
# © 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
class MapWebsite(models.Model):
_name = 'map.website'
_description = 'Map Website'
name = fields.Char(string='Map Website Name', required=True)
address_url = fields.Char(
string='URL that uses the address',
help="In this URL, {ADDRESS} will be replaced by the address.")
lat_lon_url = fields.Char(
string='URL that uses latitude and longitude',
help="In this URL, {LATITUDE} and {LONGITUDE} will be replaced by "
"the latitude and longitude (requires the module 'base_geolocalize')")
route_address_url = fields.Char(
string='Route URL that uses the addresses',
help="In this URL, {START_ADDRESS} and {DEST_ADDRESS} will be "
"replaced by the start and destination addresses.")
route_lat_lon_url = fields.Char(
string='Route URL that uses latitude and longitude',
help="In this URL, {START_LATITUDE}, {START_LONGITUDE}, "
"{DEST_LATITUDE} and {DEST_LONGITUDE} will be replaced by the "
"latitude and longitude of the start and destination adresses "
"(requires the module 'base_geolocalize').")

109
partner_external_map/models/res_partner.py

@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
# © 2015 Alexis de Lattre <alexis.delattre@akretion.com>
# © 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
from openerp.exceptions import Warning as UserError
import logging
logger = logging.getLogger(__name__)
class ResPartner(models.Model):
_inherit = 'res.partner'
@api.multi
def _address_as_string(self):
self.ensure_one()
addr = []
if self.street:
addr.append(self.street)
if self.street2:
addr.append(self.street2)
if self.city:
addr.append(self.city)
if self.state_id:
addr.append(self.state_id.name)
if self.country_id:
addr.append(self.country_id.name)
if not addr:
raise UserError(_("Address missing on partner '%s'.") % self.name)
return ' '.join(addr)
@api.model
def _prepare_url(self, url, replace):
assert url, 'Missing URL'
for key, value in replace.iteritems():
if not isinstance(value, (str, unicode)):
# for latitude and longitude which are floats
value = unicode(value)
url = url.replace(key, value)
logger.debug('Final URL: %s', url)
return url
@api.multi
def open_map(self):
map_website = self.env.user.context_map_website_id
if not map_website:
raise UserError(
_('Missing map provider: '
'you should set it in your preferences.'))
if (map_website.lat_lon_url and hasattr(self, 'partner_latitude') and
self.partner_latitude and self.partner_longitude):
url = self._prepare_url(
map_website.lat_lon_url, {
'{LATITUDE}': self.partner_latitude,
'{LONGITUDE}': self.partner_longitude})
else:
if not map_website.address_url:
raise UserError(
_("Missing parameter 'URL that uses the address' "
"for map website '%s'.") % map_website.name)
url = self._prepare_url(
map_website.address_url,
{'{ADDRESS}': self._address_as_string()})
return {
'type': 'ir.actions.act_url',
'url': url,
'target': 'new',
}
@api.multi
def open_route_map(self):
if not self.env.user.context_route_map_website_id:
raise UserError(
_('Missing route map website: '
'you should set it in your preferences.'))
map_website = self.env.user.context_route_map_website_id
if not self.env.user.context_route_start_partner_id:
raise UserError(
_('Missing start address for route map: '
'you should set it in your preferences.'))
start_partner = self.env.user.context_route_start_partner_id
if (map_website.route_lat_lon_url and
hasattr(self, 'partner_latitude') and
self.partner_latitude and self.partner_longitude and
start_partner.partner_latitude and
start_partner.partner_longitude):
url = self._prepare_url(
map_website.route_lat_lon_url, {
'{START_LATITUDE}': start_partner.partner_latitude,
'{START_LONGITUDE}': start_partner.partner_longitude,
'{DEST_LATITUDE}': self.partner_latitude,
'{DEST_LONGITUDE}': self.partner_longitude})
else:
if not map_website.route_address_url:
raise UserError(
_("Missing route URL that uses the addresses "
"for the map website '%s'") % map_website.name)
url = self._prepare_url(
map_website.route_address_url, {
'{START_ADDRESS}': start_partner._address_as_string(),
'{DEST_ADDRESS}': self._address_as_string()})
return {
'type': 'ir.actions.act_url',
'url': url,
'target': 'new',
}

42
partner_external_map/models/res_users.py

@ -0,0 +1,42 @@
# -*- coding: utf-8 -*-
# © 2015 Alexis de Lattre <alexis.delattre@akretion.com>
# © 2016 Pedro M. Baeza <pedro.baeza@tecnativa.com>
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
from openerp import models, fields, api, _
import logging
logger = logging.getLogger(__name__)
class ResUsers(models.Model):
_inherit = 'res.users'
@api.model
def _default_map_website(self):
return self.env['map.website'].search([
'|', ('address_url', '!=', False), ('lat_lon_url', '!=', False)],
limit=1)
@api.model
def _default_route_map_website(self):
return self.env['map.website'].search([
'|', ('route_address_url', '!=', False),
('route_lat_lon_url', '!=', False)], limit=1)
# begin with context_ to allow user to change it by himself
context_map_website_id = fields.Many2one(
'map.website', string='Map Website', default=_default_map_website,
domain=['|', ('address_url', '!=', False),
('lat_lon_url', '!=', False)])
# We want to give the possibility to the user to have one map provider for
# regular maps and another one for routing
context_route_map_website_id = fields.Many2one(
'map.website', string='Route Map Website',
domain=['|', ('route_address_url', '!=', False),
('route_lat_lon_url', '!=', False)],
default=_default_route_map_website,
help="Map provided used when you click on the car icon on the partner "
"form to display an itinerary.")
context_route_start_partner_id = fields.Many2one(
'res.partner', string='Start Address for Route Map')

193
partner_external_map/partner_external_maps.py

@ -1,193 +0,0 @@
# -*- coding: utf-8 -*-
# © 2015 Akretion (http://www.akretion.com/)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
from openerp import models, fields, api, _
from openerp.exceptions import Warning
import logging
logger = logging.getLogger(__name__)
class MapWebsite(models.Model):
_name = 'map.website'
_description = 'Map Website'
name = fields.Char(string='Map Website Name', required=True)
address_url = fields.Char(
string='URL that uses the address',
help="In this URL, {ADDRESS} will be replaced by the address.")
lat_lon_url = fields.Char(
string='URL that uses latitude and longitude',
help="In this URL, {LATITUDE} and {LONGITUDE} will be replaced by "
"the latitude and longitude (requires the module 'base_geolocalize')")
route_address_url = fields.Char(
string='Route URL that uses the addresses',
help="In this URL, {START_ADDRESS} and {DEST_ADDRESS} will be "
"replaced by the start and destination addresses.")
route_lat_lon_url = fields.Char(
string='Route URL that uses latitude and longitude',
help="In this URL, {START_LATITUDE}, {START_LONGITUDE}, "
"{DEST_LATITUDE} and {DEST_LONGITUDE} will be replaced by the "
"latitude and longitude of the start and destination adresses "
"(requires the module 'base_geolocalize').")
class ResUsers(models.Model):
_inherit = 'res.users'
@api.model
def _default_map_website(self):
map_website = self.env['map.website'].search([
'|', ('address_url', '!=', False), ('lat_lon_url', '!=', False)],
limit=1)
return map_website
@api.model
def _default_route_map_website(self):
map_route_website = self.env['map.website'].search([
'|',
('route_address_url', '!=', False),
('route_lat_lon_url', '!=', False)], limit=1)
return map_route_website
# begin with context_ to allow user to change it by himself
context_map_website_id = fields.Many2one(
'map.website', string='Map Website',
domain=[
'|', ('address_url', '!=', False), ('lat_lon_url', '!=', False)],
default=_default_map_website)
# We want to give the possibility to the user to have one map provider for
# regular maps and another one for routing
context_route_map_website_id = fields.Many2one(
'map.website', string='Route Map Website',
domain=[
'|',
('route_address_url', '!=', False),
('route_lat_lon_url', '!=', False)],
default=_default_route_map_website,
help="Map provided used when you click on the car icon on the partner "
"form to display an itinerary.")
context_route_start_partner_id = fields.Many2one(
'res.partner', string='Start Address for Route Map')
@api.model
def _default_map_settings(self):
"""Method called from post-install script
I can't use a default method on the field, because it would be executed
before loading map_website_data.xml, so it would not be able to set a
value"""
users = self.env['res.users'].search([])
map_website = self._default_map_website()
map_route_website = self._default_route_map_website()
logger.info('Updating user settings for maps...')
for user in users:
user.write({
'context_map_website_id': map_website.id or False,
'context_route_map_website_id': map_route_website.id or False,
'context_route_start_partner_id': user.partner_id.id or False,
})
class ResPartner(models.Model):
_inherit = 'res.partner'
@api.model
def _address_as_string(self):
addr = []
if self.street:
addr.append(self.street)
if self.street2:
addr.append(self.street2)
if self.city:
addr.append(self.city)
if self.state_id:
addr.append(self.state_id.name)
if self.country_id:
addr.append(self.country_id.name)
if not addr:
raise Warning(
_("Address missing on partner '%s'.") % self.name)
address = ' '.join(addr)
return address
@api.model
def _prepare_url(self, url, replace):
assert url, 'Missing URL'
for key, value in replace.iteritems():
if not isinstance(value, (str, unicode)):
# for latitude and longitude which are floats
value = unicode(value)
url = url.replace(key, value)
logger.debug('Final URL: %s', url)
return url
@api.multi
def open_map(self):
if not self.env.user.context_map_website_id:
raise Warning(
_('Missing map provider: '
'you should set it in your preferences.'))
map_website = self.env.user.context_map_website_id
if (
map_website.lat_lon_url and
hasattr(self, 'partner_latitude') and
self.partner_latitude and self.partner_longitude):
url = self._prepare_url(
map_website.lat_lon_url, {
'{LATITUDE}': self.partner_latitude,
'{LONGITUDE}': self.partner_longitude})
else:
if not map_website.address_url:
raise Warning(
_("Missing parameter 'URL that uses the address' "
"for map website '%s'.") % map_website.name)
url = self._prepare_url(
map_website.address_url,
{'{ADDRESS}': self._address_as_string()})
return {
'type': 'ir.actions.act_url',
'url': url,
'target': 'new',
}
@api.multi
def open_route_map(self):
if not self.env.user.context_route_map_website_id:
raise Warning(
_('Missing route map website: '
'you should set it in your preferences.'))
map_website = self.env.user.context_route_map_website_id
if not self.env.user.context_route_start_partner_id:
raise Warning(
_('Missing start address for route map: '
'you should set it in your preferences.'))
start_partner = self.env.user.context_route_start_partner_id
if (
map_website.route_lat_lon_url and
hasattr(self, 'partner_latitude') and
self.partner_latitude and
self.partner_longitude and
start_partner.partner_latitude and
start_partner.partner_longitude):
url = self._prepare_url(
map_website.route_lat_lon_url, {
'{START_LATITUDE}': start_partner.partner_latitude,
'{START_LONGITUDE}': start_partner.partner_longitude,
'{DEST_LATITUDE}': self.partner_latitude,
'{DEST_LONGITUDE}': self.partner_longitude})
else:
if not map_website.route_address_url:
raise Warning(
_("Missing route URL that uses the addresses "
"for the map website '%s'") % map_website.name)
url = self._prepare_url(
map_website.route_address_url, {
'{START_ADDRESS}': start_partner._address_as_string(),
'{DEST_ADDRESS}': self._address_as_string()})
return {
'type': 'ir.actions.act_url',
'url': url,
'target': 'new',
}

11
partner_external_map/post_install.py

@ -1,11 +0,0 @@
# -*- coding: utf-8 -*-
# © 2015 Akretion (http://www.akretion.com)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
from openerp import SUPERUSER_ID
def set_default_map_settings(cr, pool):
pool['res.users']._default_map_settings(cr, SUPERUSER_ID)
return

BIN
partner_external_map/static/description/icon.png

Before

Width: 128  |  Height: 128  |  Size: 9.2 KiB

After

Width: 128  |  Height: 128  |  Size: 16 KiB

2887
partner_external_map/static/description/icon.svg
File diff suppressed because it is too large
View File

0
partner_external_map/map_website_view.xml → partner_external_map/views/map_website_view.xml

0
partner_external_map/partner_view.xml → partner_external_map/views/res_partner_view.xml

0
partner_external_map/users_view.xml → partner_external_map/views/res_users_view.xml

Loading…
Cancel
Save