issue4004
review9441002
This commit is contained in:
Cédric Krier
2014-08-04 16:41:49 +02:00
parent d6e46533f6
commit 7065678e77
9 changed files with 206 additions and 1 deletions
+2
View File
@@ -1,3 +1,5 @@
* Add zip
Version 3.2.0 - 2014-04-21
* Bug fixes (see mercurial logs for details)
+1
View File
@@ -9,4 +9,5 @@ def register():
Pool.register(
Country,
Subdivision,
Zip,
module='country', type_='model')
+21 -1
View File
@@ -1,8 +1,9 @@
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
from trytond.model import ModelView, ModelSQL, fields
from trytond.pyson import Eval
__all__ = ['Country', 'Subdivision']
__all__ = ['Country', 'Subdivision', 'Zip']
class Country(ModelSQL, ModelView):
@@ -194,3 +195,22 @@ class Subdivision(ModelSQL, ModelView):
values['code'] = values['code'].upper()
args.extend((subdivisions, values))
super(Subdivision, cls).write(*args)
class Zip(ModelSQL, ModelView):
"Zip"
__name__ = 'country.zip'
country = fields.Many2One('country.country', 'Country', required=True,
select=True, ondelete='CASCADE')
subdivision = fields.Many2One('country.subdivision', 'Subdivision',
select=True, ondelete='CASCADE',
domain=[('country', '=', Eval('country', -1))],
depends=['country'])
zip = fields.Char('Zip')
city = fields.Char('City')
@classmethod
def __setup__(cls):
super(Zip, cls).__setup__()
cls._order.insert(0, ('country', 'ASC'))
cls._order.insert(0, ('zip', 'ASC'))
+49
View File
@@ -46,6 +46,39 @@ this repository contains the full copyright notices and license terms. -->
<field name="name">subdivision_tree</field>
</record>
<record model="ir.ui.view" id="zip_view_form">
<field name="model">country.zip</field>
<field name="type">form</field>
<field name="name">zip_form</field>
</record>
<record model="ir.ui.view" id="zip_view_list">
<field name="model">country.zip</field>
<field name="type">tree</field>
<field name="name">zip_list</field>
</record>
<record model="ir.action.act_window" id="act_zip_form">
<field name="name">Zip</field>
<field name="res_model">country.zip</field>
<field name="domain">[('country', 'in', Eval('active_ids'))]</field>
</record>
<record model="ir.action.act_window.view" id="act_zip_form_view1">
<field name="sequence" eval="10"/>
<field name="view" ref="zip_view_list"/>
<field name="act_window" ref="act_zip_form"/>
</record>
<record model="ir.action.act_window.view" id="act_zip_form_view2">
<field name="sequence" eval="20"/>
<field name="view" ref="zip_view_form"/>
<field name="act_window" ref="act_zip_form"/>
</record>
<record model="ir.action.keyword"
id="act_zip_form_keyword1">
<field name="keyword">form_relate</field>
<field name="model">country.country,-1</field>
<field name="action" ref="act_zip_form"/>
</record>
</data>
<!--
@@ -36345,5 +36378,21 @@ this repository contains the full copyright notices and license terms. -->
<field name="perm_delete" eval="True"/>
</record>
<record model="ir.model.access" id="access_country_zip">
<field name="model" search="[('model', '=', 'country.zip')]"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="False"/>
<field name="perm_create" eval="False"/>
<field name="perm_delete" eval="False"/>
</record>
<record model="ir.model.access" id="access_country_zip_admin">
<field name="model" search="[('model', '=', 'country.zip')]"/>
<field name="group" ref="res.group_admin"/>
<field name="perm_read" eval="True"/>
<field name="perm_write" eval="True"/>
<field name="perm_create" eval="True"/>
<field name="perm_delete" eval="True"/>
</record>
</data>
</tryton>
+6
View File
@@ -20,3 +20,9 @@ Subdivision
A subdivision is defined by a name, a code and a type (e.g, Capital
City, Province, Emirate, etc)
Zip
***
A zip links a zip code of a country to a city.
+101
View File
@@ -0,0 +1,101 @@
#!/usr/bin/env python
#This file is part of Tryton. The COPYRIGHT file at the top level of
#this repository contains the full copyright notices and license terms.
import urllib2
import zipfile
import csv
import sys
from io import BytesIO
from argparse import ArgumentParser
try:
from progressbar import ProgressBar, Bar, ETA, SimpleProgress
except ImportError:
ProgressBar = None
from proteus import Model, config
def clean(code):
sys.stderr.write('Cleaning')
Zip = Model.get('country.zip')
Zip._proxy.delete(
[z.id for z in Zip.find([('country.code', '=', code)])], {})
print >> sys.stderr, '.'
def fetch(code):
sys.stderr.write('Fetching')
url = 'http://download.geonames.org/export/zip/%s.zip' % code
responce = urllib2.urlopen(url)
data = responce.read()
with zipfile.ZipFile(BytesIO(data)) as zf:
data = zf.read('%s.txt' % code)
print >> sys.stderr, '.'
return data
def import_(data):
Zip = Model.get('country.zip')
Country = Model.get('country.country')
Subdivision = Model.get('country.subdivision')
print >> sys.stderr, 'Importing'
def get_country(code):
country = countries.get(code)
if not country:
country, = Country.find([('code', '=', code)])
countries[code] = country
return country
countries = {}
def get_subdivision(country, code):
code = '%s-%s' % (country, code)
subdivision = subdivisions.get(code)
if not subdivision:
try:
subdivision, = Subdivision.find([('code', '=', code)])
except ValueError:
return
subdivisions[code] = subdivision
return subdivision
subdivisions = {}
if ProgressBar:
pbar = ProgressBar(
widgets=[SimpleProgress(), Bar(), ETA()])
else:
pbar = iter
for row in pbar(list(csv.DictReader(BytesIO(data),
fieldnames=_fieldnames, delimiter='\t'))):
country = get_country(row['country'])
subdivision = get_subdivision(row['country'], row['code1'])
Zip(country=country, subdivision=subdivision, zip=row['postal'],
city=row['place']).save()
_fieldnames = ['country', 'postal', 'place', 'name1', 'code1',
'name2', 'code2', 'name3', 'code3', 'latitude', 'longitude', 'accuracy']
def main(database, password, codes, config_file=None):
config.set_trytond(database, password=password, config_file=config_file)
for code in codes:
print >> sys.stderr, code
code = code.upper()
clean(code)
import_(fetch(code))
if __name__ == '__main__':
parser = ArgumentParser()
parser.add_argument('-p', '--password', dest='password', default='admin',
help='admin password (default: %(default)s)')
parser.add_argument('-d', '--database', dest='database')
parser.add_argument('-c', '--config', dest='config_file',
help='the trytond config file')
parser.add_argument('codes', nargs='+')
args = parser.parse_args()
if not args.database:
parser.error('Missing database')
main(args.database, args.password, args.codes, args.config_file)
+4
View File
@@ -65,6 +65,7 @@ setup(name=name,
'trytond.modules.country': (info.get('xml', [])
+ ['tryton.cfg', 'view/*.xml', 'locale/*.po']),
},
scripts=['scripts/trytond_import_zip'],
classifiers=[
'Development Status :: 5 - Production/Stable',
'Environment :: Plugins',
@@ -90,6 +91,9 @@ setup(name=name,
],
license='GPL-3',
install_requires=requires,
extras_require={
'GeoNames': [get_require_version('proteus')],
},
zip_safe=False,
entry_points="""
[trytond.modules]
+13
View File
@@ -0,0 +1,13 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<form string="Zip">
<label name="country"/>
<field name="country"/>
<label name="subdivision"/>
<field name="subdivision"/>
<label name="zip"/>
<field name="zip"/>
<label name="city"/>
<field name="city"/>
</form>
+9
View File
@@ -0,0 +1,9 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tree string="Zip">
<field name="country"/>
<field name="subdivision"/>
<field name="zip"/>
<field name="city"/>
</tree>