You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

128 lines
5.3 KiB

  1. # -*- encoding: utf-8 -*-
  2. ##############################################################################
  3. #
  4. # Base Location Geonames Import module for OpenERP
  5. # Copyright (C) 2014 Akretion (http://www.akretion.com)
  6. # @author Alexis de Lattre <alexis.delattre@akretion.com>
  7. #
  8. # This program is free software: you can redistribute it and/or modify
  9. # it under the terms of the GNU Affero General Public License as
  10. # published by the Free Software Foundation, either version 3 of the
  11. # License, or (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU Affero General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU Affero General Public License
  19. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. #
  21. ##############################################################################
  22. from openerp.osv import orm, fields
  23. from openerp.tools.translate import _
  24. import requests
  25. import tempfile
  26. import StringIO
  27. import unicodecsv
  28. import zipfile
  29. import os
  30. import logging
  31. logger = logging.getLogger(__name__)
  32. class better_zip_geonames_import(orm.TransientModel):
  33. _name = 'better.zip.geonames.import'
  34. _description = 'Import Better Zip from Geonames'
  35. _rec_name = 'country_id'
  36. _columns = {
  37. 'country_id': fields.many2one('res.country', 'Country', required=True),
  38. }
  39. def _prepare_better_zip(
  40. self, cr, uid, row, country_id, states, context=None):
  41. '''This function is designed to be inherited'''
  42. state_id = False
  43. if states and row[4] and row[4] in states:
  44. state_id = states[row[4].upper()]
  45. vals = {
  46. 'name': row[1],
  47. 'city': row[2],
  48. 'state_id': state_id,
  49. 'country_id': country_id,
  50. }
  51. return vals
  52. def create_better_zip(
  53. self, cr, uid, row, country_id, country_code, states,
  54. context=None):
  55. bzip_id = False
  56. if row[0] != country_code:
  57. raise orm.except_orm(
  58. _('Error:'),
  59. _("The country code inside the file (%s) doesn't "
  60. "correspond to the selected country (%s).")
  61. % (row[0], country_code))
  62. logger.debug('ZIP = %s - City = %s' % (row[1], row[2]))
  63. if row[1] and row[2]:
  64. vals = self._prepare_better_zip(
  65. cr, uid, row, country_id, states, context=context)
  66. if vals:
  67. bzip_id = self.pool['res.better.zip'].create(
  68. cr, uid, vals, context=context)
  69. return bzip_id
  70. def run_import(self, cr, uid, ids, context=None):
  71. assert len(ids) == 1, 'Only one ID for the better zip import wizard'
  72. bzip_obj = self.pool['res.better.zip']
  73. wizard = self.browse(cr, uid, ids[0], context=context)
  74. country_id = wizard.country_id.id
  75. country_code = wizard.country_id.code.upper()
  76. url = 'http://download.geonames.org/export/zip/%s.zip' % country_code
  77. logger.info('Starting to download %s' % url)
  78. res_request = requests.get(url)
  79. if res_request.status_code != requests.codes.ok:
  80. raise orm.except_orm(
  81. _('Error:'),
  82. _('Got an error %d when trying to download the file %s.')
  83. % (res_request.status_code, url))
  84. bzip_ids_to_delete = bzip_obj.search(
  85. cr, uid, [('country_id', '=', country_id)], context=context)
  86. if bzip_ids_to_delete:
  87. cr.execute('SELECT id FROM res_better_zip WHERE id in %s '
  88. 'FOR UPDATE NOWAIT', (tuple(bzip_ids_to_delete), ))
  89. bzip_obj.unlink(cr, uid, bzip_ids_to_delete, context=context)
  90. logger.info(
  91. '%d better zip entries deleted for country %s'
  92. % (len(bzip_ids_to_delete), wizard.country_id.name))
  93. state_ids = self.pool['res.country.state'].search(
  94. cr, uid, [('country_id', '=', country_id)], context=context)
  95. states = {}
  96. # key = code of the state ; value = ID of the state in OpenERP
  97. if state_ids:
  98. states_r = self.pool['res.country.state'].read(
  99. cr, uid, state_ids, ['code', 'country_id'], context=context)
  100. for state in states_r:
  101. states[state['code'].upper()] = state['id']
  102. f_geonames = zipfile.ZipFile(StringIO.StringIO(res_request.content))
  103. tempdir = tempfile.mkdtemp(prefix='openerp')
  104. f_geonames.extract('%s.txt' % country_code, tempdir)
  105. logger.info('The geonames zipfile has been decompressed')
  106. data_file = open(os.path.join(tempdir, '%s.txt' % country_code), 'r')
  107. data_file.seek(0)
  108. logger.info(
  109. 'Starting to create the better zip entries %s state information'
  110. % (states and 'with' or 'without'))
  111. for row in unicodecsv.reader(
  112. data_file, encoding='utf-8', delimiter=' '):
  113. self.create_better_zip(
  114. cr, uid, row, country_id, country_code, states,
  115. context=context)
  116. data_file.close()
  117. logger.info(
  118. 'The wizard to create better zip entries from geonames '
  119. 'has been successfully completed.')
  120. return True