diff --git a/CHANGELOG b/CHANGELOG index 7d72077091..07c0f295e4 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,5 @@ +* Add zip + Version 3.2.0 - 2014-04-21 * Bug fixes (see mercurial logs for details) diff --git a/__init__.py b/__init__.py index 1a180eedca..55eb99c86f 100644 --- a/__init__.py +++ b/__init__.py @@ -9,4 +9,5 @@ def register(): Pool.register( Country, Subdivision, + Zip, module='country', type_='model') diff --git a/country.py b/country.py index d499226059..25eef8c5c1 100644 --- a/country.py +++ b/country.py @@ -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')) diff --git a/country.xml b/country.xml index 16da48cad2..7a8f267a22 100644 --- a/country.xml +++ b/country.xml @@ -46,6 +46,39 @@ this repository contains the full copyright notices and license terms. --> subdivision_tree + + country.zip + form + zip_form + + + country.zip + tree + zip_list + + + + Zip + country.zip + [('country', 'in', Eval('active_ids'))] + + + + + + + + + + + + + form_relate + country.country,-1 + + + + + + + + + + + + + + + + + + + diff --git a/doc/index.rst b/doc/index.rst index e2a71eb272..6a70403d0b 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -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. diff --git a/scripts/trytond_import_zip b/scripts/trytond_import_zip new file mode 100755 index 0000000000..1954904da3 --- /dev/null +++ b/scripts/trytond_import_zip @@ -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) diff --git a/setup.py b/setup.py index a7bb6cf801..fb93f71f47 100644 --- a/setup.py +++ b/setup.py @@ -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] diff --git a/view/zip_form.xml b/view/zip_form.xml new file mode 100644 index 0000000000..e3819ab805 --- /dev/null +++ b/view/zip_form.xml @@ -0,0 +1,13 @@ + + +
+