Browse Source

[IMP] base_location_geonames_import: Several improvements and added hooks

* Added Icon.
* Improve module description and extracted to README.rst.
* Pass country instead of country_id for advance comparisons.
* Allow to transform city name.
* Some code style.
* Do not remove all entries of a country, but only not found.
* Include hooks for transforming some things.
* Include spanish translation.

[FIX] base_location_geonames_import: Use self.env and recordsets
pull/643/head
Pedro M. Baeza 10 years ago
parent
commit
de4790a8fc
  1. 61
      base_location_geonames_import/README.rst
  2. 30
      base_location_geonames_import/__openerp__.py
  3. 4
      base_location_geonames_import/i18n/base_location_geonames_import.pot
  4. 68
      base_location_geonames_import/i18n/es.po
  5. 4
      base_location_geonames_import/i18n/fr.po
  6. 2
      base_location_geonames_import/i18n/it.po
  7. BIN
      base_location_geonames_import/static/description/icon.png
  8. 782
      base_location_geonames_import/static/description/icon.svg
  9. 96
      base_location_geonames_import/wizard/geonames_import.py
  10. 68
      base_location_geonames_import/wizard/geonames_import_view.xml

61
base_location_geonames_import/README.rst

@ -0,0 +1,61 @@
Base Location Geonames Import
=============================
This module adds a wizard to import better zip entries from Geonames database.
Installation
============
For installing this module, you need these Python libraries: requests and
unicodecsv.
Configuration
=============
For seeing the menu, you need to activate *Technical features* option in your
user and to be *Sales manager*.
If want want/need to modify the default URL
(http://download.geonames.org/export/zip/), you can set the 'geonames.url'
system parameter.
Usage
=====
Go to *Sales > Configuration > Address book > Localization > Import from Geonames*,
and click on it to open a wizard.
When you start the wizard, it will ask you to select a country. Then, for the
selected country, it will delete all the current better zip entries, download
the latest version of the list of cities from geonames.org and create new
better zip entries.
Credits
=======
Contributors
------------
* Alexis de Lattre <alexis.delattre@akretion.com>
* Lorenzo Battistini <lorenzo.battistini@agilebg.com>
* Pedro M. Baeza <pedro.baeza@serviciosbaeza.com>
Icon
----
* http://icon-park.com/icon/location-map-pin-orange3/
* http://commons.wikimedia.org/wiki/File:View-refresh.svg
Maintainer
----------
.. image:: http://odoo-community.org/logo.png
:alt: Odoo Community Association
:target: http://odoo-community.org
This module is maintained by the OCA.
OCA, or the Odoo Community Association, is a nonprofit organization whose
mission is to support the collaborative development of Odoo features and
promote its widespread use.
To contribute to this module, please visit http://odoo-community.org.

30
base_location_geonames_import/__openerp__.py

@ -29,31 +29,11 @@
'category': 'Extra Tools', 'category': 'Extra Tools',
'license': 'AGPL-3', 'license': 'AGPL-3',
'summary': 'Import better zip entries from Geonames', 'summary': 'Import better zip entries from Geonames',
'description': """
Base Location Geonames Import
=============================
This module adds a wizard to import better zip entries from Geonames
(http://download.geonames.org/export/zip/).
If want want/need to modify the URL, you can set the 'geonames.url'
system parameter.
When you start the wizard,
it will ask you to select a country. Then, for the selected country,
it will delete all the current better zip entries, download the latest version
of the list of cities from geonames.org and create new better zip entries.
Please contact Alexis de Lattre from Akretion <alexis.delattre@akretion.com>
for any help or question about this module.
Contributors
------------
- Alexis de Lattre <alexis.delattre@akretion.com>
- Lorenzo Battistini <lorenzo.battistini@agilebg.com>
""",
'author': "Akretion,Odoo Community Association (OCA)",
'author': 'Akretion,'
'Agile Business Group,'
'Antiun Ingeniería S.L.,'
'Serv. Tecnol. Avanzados - Pedro M. Baeza,'
'Odoo Community Association (OCA)',
'website': 'http://www.akretion.com', 'website': 'http://www.akretion.com',
'depends': ['base_location'], 'depends': ['base_location'],
'external_dependencies': {'python': ['requests', 'unicodecsv']}, 'external_dependencies': {'python': ['requests', 'unicodecsv']},

4
base_location_geonames_import/i18n/base_location_geonames_import.pot

@ -34,7 +34,7 @@ msgstr ""
#. module: base_location_geonames_import #. module: base_location_geonames_import
#: view:better.zip.geonames.import:0 #: view:better.zip.geonames.import:0
msgid "For the country selected above, this wizard will DELETE ALL THE CURRENT BETTER ZIP ENTRIES, download the latest version of the list of cities from geonames.org and create new better zip entries."
msgid "For the country selected above, this wizard will download the latest version of the list of cities from geonames.org, create new location entries if not found already in the system, and DELETE MISSING ENTRIES from new file."
msgstr "" msgstr ""
#. module: base_location_geonames_import #. module: base_location_geonames_import
@ -57,7 +57,7 @@ msgstr ""
#: view:better.zip.geonames.import:0 #: view:better.zip.geonames.import:0
#: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action #: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action
#: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu #: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu
msgid "Import Geonames"
msgid "Import from Geonames"
msgstr "" msgstr ""
#. module: base_location_geonames_import #. module: base_location_geonames_import

68
base_location_geonames_import/i18n/es.po

@ -0,0 +1,68 @@
# Translation of OpenERP Server.
# This file contains the translation of the following modules:
# * base_location_geonames_import
#
msgid ""
msgstr ""
"Project-Id-Version: OpenERP Server 7.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2014-04-11 20:55+0000\n"
"PO-Revision-Date: 2014-04-11 20:55+0000\n"
"Last-Translator: <>\n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: base_location_geonames_import
#: view:better.zip.geonames.import:0
msgid "Cancel"
msgstr "Cancelar"
#. module: base_location_geonames_import
#: field:better.zip.geonames.import,country_id:0
msgid "Country"
msgstr "País"
#. module: base_location_geonames_import
#: code:addons/base_location_geonames_import/wizard/geonames_import.py:66
#: code:addons/base_location_geonames_import/wizard/geonames_import.py:90
#, python-format
msgid "Error:"
msgstr "Error:"
#. module: base_location_geonames_import
#: view:better.zip.geonames.import:0
msgid "For the country selected above, this wizard will download the latest version of the list of cities from geonames.org, create new location entries if not found already in the system, and DELETE MISSING ENTRIES from new file."
msgstr "Para el país seleccionado arriba, este asistente descargará la última versión de la lista de ciudades de geonames.org, creará nuevas entradas de ubicaciones si no se encuentran ya en el sistema, y BORRARÁ LOS REGISTROS DESAPARECIDOS en el nuevo archivo."
#. module: base_location_geonames_import
#: code:addons/base_location_geonames_import/wizard/geonames_import.py:91
#, python-format
msgid "Got an error %d when trying to download the file %s."
msgstr "Se obtuvo un error %d cuando se descargaba el archivo %s."
#. module: base_location_geonames_import
#: view:better.zip.geonames.import:0
msgid "Import"
msgstr "Importar"
#. module: base_location_geonames_import
#: model:ir.model,name:base_location_geonames_import.model_better_zip_geonames_import
msgid "Import Better Zip from Geonames"
msgstr "Importar ubicaciones de Geonames"
#. module: base_location_geonames_import
#: view:better.zip.geonames.import:0
#: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action
#: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu
msgid "Import from Geonames"
msgstr "Importar de GeoNames"
#. module: base_location_geonames_import
#: code:addons/base_location_geonames_import/wizard/geonames_import.py:67
#, python-format
msgid "The country code inside the file (%s) doesn't correspond to the selected country (%s)."
msgstr "El código de país dentro del archivo (%s) no se corresponde con el país seleccionado (%s)."

4
base_location_geonames_import/i18n/fr.po

@ -57,8 +57,8 @@ msgstr "Import Better Zip from Geonames"
#: view:better.zip.geonames.import:0 #: view:better.zip.geonames.import:0
#: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action #: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action
#: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu #: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu
msgid "Import Geonames"
msgstr "Importer Geonames"
msgid "Import from Geonames"
msgstr "Importer de Geonames"
#. module: base_location_geonames_import #. module: base_location_geonames_import
#: code:addons/base_location_geonames_import/wizard/geonames_import.py:67 #: code:addons/base_location_geonames_import/wizard/geonames_import.py:67

2
base_location_geonames_import/i18n/it.po

@ -66,7 +66,7 @@ msgstr "Importa Better Zip da Geonames"
#: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action #: model:ir.actions.act_window,name:base_location_geonames_import.better_zip_geonames_import_action
#: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu #: model:ir.ui.menu,name:base_location_geonames_import.better_zip_geonames_import_menu
msgid "Import Geonames" msgid "Import Geonames"
msgstr "Importa Geonames"
msgstr "Importa da Geonames"
#. module: base_location_geonames_import #. module: base_location_geonames_import
#: code:addons/base_location_geonames_import/wizard/geonames_import.py:67 #: code:addons/base_location_geonames_import/wizard/geonames_import.py:67

BIN
base_location_geonames_import/static/description/icon.png

After

Width: 128  |  Height: 128  |  Size: 13 KiB

782
base_location_geonames_import/static/description/icon.svg
File diff suppressed because it is too large
View File

96
base_location_geonames_import/wizard/geonames_import.py

@ -27,15 +27,19 @@ from openerp.exceptions import Warning
import requests import requests
import tempfile import tempfile
import StringIO import StringIO
import unicodecsv
import zipfile import zipfile
import os import os
import logging import logging
try:
import unicodecsv
except ImportError:
unicodecsv = None
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
class better_zip_geonames_import(models.TransientModel):
class BetterZipGeonamesImport(models.TransientModel):
_name = 'better.zip.geonames.import' _name = 'better.zip.geonames.import'
_description = 'Import Better Zip from Geonames' _description = 'Import Better Zip from Geonames'
_rec_name = 'country_id' _rec_name = 'country_id'
@ -43,88 +47,106 @@ class better_zip_geonames_import(models.TransientModel):
country_id = fields.Many2one('res.country', 'Country', required=True) country_id = fields.Many2one('res.country', 'Country', required=True)
@api.model @api.model
def _prepare_better_zip(self, row, country_id):
state = self.select_or_create_state(row, country_id)
def transform_city_name(self, city, country):
"""Override it for transforming city name (if needed)
:param city: Original city name
:param country: Country record
:return: Transformed city name
"""
return city
@api.model
def _domain_search_better_zip(self, row, country):
return [('name', '=', row[1]),
('city', '=', self.transform_city_name(row[2], country)),
('country_id', '=', country.id)]
@api.model
def _prepare_better_zip(self, row, country):
state = self.select_or_create_state(row, country)
vals = { vals = {
'name': row[1], 'name': row[1],
'city': row[2],
'city': self.transform_city_name(row[2], country),
'state_id': state.id, 'state_id': state.id,
'country_id': country_id,
'country_id': country.id,
} }
return vals return vals
@api.model @api.model
def create_better_zip(
self, row, country_id, country_code):
bzip_id = False
if row[0] != country_code:
def create_better_zip(self, row, country):
if row[0] != country.code:
raise Warning( raise Warning(
_('Error:'),
_("The country code inside the file (%s) doesn't " _("The country code inside the file (%s) doesn't "
"correspond to the selected country (%s).") "correspond to the selected country (%s).")
% (row[0], country_code))
% (row[0], country.code))
logger.debug('ZIP = %s - City = %s' % (row[1], row[2])) logger.debug('ZIP = %s - City = %s' % (row[1], row[2]))
if row[1] and row[2]: if row[1] and row[2]:
vals = self._prepare_better_zip(row, country_id)
if vals:
bzip_id = self.env['res.better.zip'].create(vals)
return bzip_id
zip_model = self.env['res.better.zip']
zips = zip_model.search(self._domain_search_better_zip(
row, country))
if zips:
return zips[0]
else:
vals = self._prepare_better_zip(row, country)
if vals:
return zip_model.create(vals)
else:
return False
@api.model @api.model
def select_or_create_state( def select_or_create_state(
self, row, country_id, code_row_index=4, name_row_index=3
):
self, row, country, code_row_index=4, name_row_index=3):
states = self.env['res.country.state'].search([ states = self.env['res.country.state'].search([
('country_id', '=', country_id),
('country_id', '=', country.id),
('code', '=', row[code_row_index]), ('code', '=', row[code_row_index]),
]) ])
if len(states) > 1: if len(states) > 1:
raise Warning( raise Warning(
_("Too many states with code %s for counrty %s")
% (row[code_row_index], country_id))
_("Too many states with code %s for country %s")
% (row[code_row_index], country.code))
if len(states) == 1: if len(states) == 1:
return states[0] return states[0]
else: else:
return self.env['res.country.state'].create({ return self.env['res.country.state'].create({
'name': row[name_row_index], 'name': row[name_row_index],
'code': row[code_row_index], 'code': row[code_row_index],
'country_id': country_id
'country_id': country.id
}) })
@api.one @api.one
def run_import(self): def run_import(self):
bzip_obj = self.env['res.better.zip']
country_id = self.country_id.id
country_code = self.country_id.code.upper()
config_url = self.pool['ir.config_parameter'].get_param(
self._cr, self._uid, 'geonames.url',
zip_model = self.env['res.better.zip']
country_code = self.country_id.code
config_url = self.env['ir.config_parameter'].get_param(
'geonames.url',
default='http://download.geonames.org/export/zip/%s.zip') default='http://download.geonames.org/export/zip/%s.zip')
url = config_url % country_code url = config_url % country_code
logger.info('Starting to download %s' % url) logger.info('Starting to download %s' % url)
res_request = requests.get(url) res_request = requests.get(url)
if res_request.status_code != requests.codes.ok: if res_request.status_code != requests.codes.ok:
raise Warning( raise Warning(
_('Error:'),
_('Got an error %d when trying to download the file %s.') _('Got an error %d when trying to download the file %s.')
% (res_request.status_code, url)) % (res_request.status_code, url))
bzip_ids_to_delete = bzip_obj.search([('country_id', '=', country_id)])
if bzip_ids_to_delete:
bzip_ids_to_delete.unlink()
logger.info(
'%d better zip entries deleted for country %s'
% (len(bzip_ids_to_delete), self.country_id.name))
# Store current record list
zips_to_delete = zip_model.search(
[('country_id', '=', self.country_id.id)])
f_geonames = zipfile.ZipFile(StringIO.StringIO(res_request.content)) f_geonames = zipfile.ZipFile(StringIO.StringIO(res_request.content))
tempdir = tempfile.mkdtemp(prefix='openerp') tempdir = tempfile.mkdtemp(prefix='openerp')
f_geonames.extract('%s.txt' % country_code, tempdir) f_geonames.extract('%s.txt' % country_code, tempdir)
logger.info('The geonames zipfile has been decompressed') logger.info('The geonames zipfile has been decompressed')
data_file = open(os.path.join(tempdir, '%s.txt' % country_code), 'r') data_file = open(os.path.join(tempdir, '%s.txt' % country_code), 'r')
data_file.seek(0) data_file.seek(0)
logger.info(
'Starting to create the better zip entries')
logger.info('Starting to create the better zip entries')
for row in unicodecsv.reader( for row in unicodecsv.reader(
data_file, encoding='utf-8', delimiter=' '): data_file, encoding='utf-8', delimiter=' '):
self.create_better_zip(row, country_id, country_code)
zip = self.create_better_zip(row, self.country_id)
if zip in zips_to_delete:
zips_to_delete -= zip
data_file.close() data_file.close()
if zips_to_delete:
zips_to_delete.unlink()
logger.info('%d better zip entries deleted for country %s' %
(len(zips_to_delete), self.country_id.name))
logger.info( logger.info(
'The wizard to create better zip entries from geonames ' 'The wizard to create better zip entries from geonames '
'has been successfully completed.') 'has been successfully completed.')

68
base_location_geonames_import/wizard/geonames_import_view.xml

@ -1,44 +1,38 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2014 Akretion (http://www.akretion.com/)
@author: Alexis de Lattre <alexis.delattre@akretion.com>
The licence is in the file __openerp__.py
-->
<openerp> <openerp>
<data>
<data>
<record id="better_zip_geonames_import_form" model="ir.ui.view">
<field name="name">asterisk.server.company</field>
<field name="model">better.zip.geonames.import</field>
<field name="arch" type="xml">
<form string="Import Geonames" version="7.0">
<group name="main">
<field name="country_id"/>
<label string="For the country selected above, this wizard will DELETE ALL THE CURRENT BETTER ZIP ENTRIES, download the latest version of the list of cities from geonames.org and create new better zip entries."
colspan="2" name="import-help"/>
</group>
<footer>
<button name="run_import" type="object"
class="oe_highlight" string="Import"/>
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record id="better_zip_geonames_import_form" model="ir.ui.view">
<field name="name">asterisk.server.company</field>
<field name="model">better.zip.geonames.import</field>
<field name="arch" type="xml">
<form string="Import from Geonames">
<group name="main">
<field name="country_id"/>
<label string="For the country selected above, this wizard will download the latest version of the list of cities from geonames.org, create new location entries if not found already in the system, and DELETE MISSING ENTRIES from new file."
colspan="2" name="import-help"/>
</group>
<footer>
<button name="run_import" type="object"
class="oe_highlight" string="Import"/>
<button special="cancel" string="Cancel" class="oe_link"/>
</footer>
</form>
</field>
</record>
<record id="better_zip_geonames_import_action" model="ir.actions.act_window">
<field name="name">Import Geonames</field>
<field name="res_model">better.zip.geonames.import</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<record id="better_zip_geonames_import_action" model="ir.actions.act_window">
<field name="name">Import from Geonames</field>
<field name="res_model">better.zip.geonames.import</field>
<field name="view_type">form</field>
<field name="view_mode">form</field>
<field name="target">new</field>
</record>
<menuitem id="better_zip_geonames_import_menu"
action="better_zip_geonames_import_action"
parent="base.menu_localisation"
sequence="50"/>
<menuitem id="better_zip_geonames_import_menu"
action="better_zip_geonames_import_action"
parent="base.menu_localisation"
sequence="50"/>
</data>
</data>
</openerp> </openerp>
Loading…
Cancel
Save