diff --git a/addons/sale/wizard/sale_make_invoice_advance.py b/addons/sale/wizard/sale_make_invoice_advance.py index ac7d9587d224c74a7526bc8560fa9f48128c7137..c04685a84aaf6b0d22eb3ae88b5b6e709baf90a4 100644 --- a/addons/sale/wizard/sale_make_invoice_advance.py +++ b/addons/sale/wizard/sale_make_invoice_advance.py @@ -65,7 +65,7 @@ class SaleAdvancePaymentInv(models.TransientModel): account_id = False if self.product_id.id: - account_id = self.product_id.property_account_income_id.id + account_id = self.product_id.property_account_income_id.id or self.product_id.categ_id.property_account_income_categ_id.id if not account_id: inc_acc = ir_property_obj.get('property_account_income_categ_id', 'product.category') account_id = order.fiscal_position_id.map_account(inc_acc).id if inc_acc else False diff --git a/addons/website/geoipresolver.py b/addons/website/geoipresolver.py new file mode 100644 index 0000000000000000000000000000000000000000..1f9b0e2272453753afe131450670ca9d136ec9aa --- /dev/null +++ b/addons/website/geoipresolver.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +import os.path + +try: + import GeoIP # Legacy +except ImportError: + GeoIP = None + +try: + import geoip2 + import geoip2.database +except ImportError: + geoip2 = None + +class GeoIPResolver(object): + def __init__(self, fname): + self.fname = fname + try: + self._db = geoip2.database.Reader(fname) + self.version = 2 + except Exception: + try: + self._db = GeoIP.open(fname, GeoIP.GEOIP_STANDARD) + self.version = 1 + assert self._db.database_info is not None + except Exception: + raise ValueError('Invalid GeoIP database: %r' % fname) + + def __del__(self): + if self.version == 2: + self._db.close() + + @classmethod + def open(cls, fname): + if not GeoIP and not geoip2: + return None + if not os.path.exists(fname): + return None + return GeoIPResolver(fname) + + def resolve(self, ip): + if self.version == 1: + return self._db.record_by_addr(ip) or {} + elif self.version == 2: + try: + r = self._db.city(ip) + except (ValueError, geoip2.errors.AddressNotFoundError): + return {} + return { + 'city': r.city.name, + 'country_code': r.country.iso_code, + 'country_name': r.country.name, + 'region': r.subdivisions[0].iso_code if r.subdivisions else None, + 'time_zone': r.location.time_zone, + } + + # compat + def record_by_addr(self, addr): + return self.resolve(addr) diff --git a/addons/website/models/ir_http.py b/addons/website/models/ir_http.py index ae25b716c59c227f367da7079254f5b7b5f74095..e04b486a54a028ca515689ed1748e0faa278ca79 100644 --- a/addons/website/models/ir_http.py +++ b/addons/website/models/ir_http.py @@ -14,7 +14,7 @@ import odoo from odoo import api, models from odoo import SUPERUSER_ID from odoo.http import request -from odoo.tools import config +from odoo.tools import config, ustr from odoo.exceptions import QWebException from odoo.tools.safe_eval import safe_eval @@ -22,6 +22,8 @@ from odoo.addons.base import ir from odoo.addons.website.models.website import slug, url_for, _UNSLUG_RE +from ..geoipresolver import GeoIPResolver + logger = logging.getLogger(__name__) # global resolver (GeoIP API is thread-safe, for multithreaded workers) @@ -100,25 +102,18 @@ class Http(models.AbstractModel): if odoo._geoip_resolver is not None: cls._geoip_resolver = odoo._geoip_resolver return + geofile = config.get('geoip_database') try: - import GeoIP - # updated database can be downloaded on MaxMind website - # http://dev.maxmind.com/geoip/legacy/install/city/ - geofile = config.get('geoip_database') - if os.path.exists(geofile): - odoo._geoip_resolver = GeoIP.open(geofile, GeoIP.GEOIP_STANDARD) - else: - odoo._geoip_resolver = False - logger.warning('GeoIP database file %r does not exists, apt-get install geoip-database-contrib or download it from http://dev.maxmind.com/geoip/legacy/install/city/', geofile) - except ImportError: - odoo._geoip_resolver = False + odoo._geoip_resolver = GeoIPResolver.open(geofile) or False + except Exception as e: + logger.warning('Cannot load GeoIP: %s', ustr(e)) @classmethod def _geoip_resolve(cls): if 'geoip' not in request.session: record = {} if odoo._geoip_resolver and request.httprequest.remote_addr: - record = odoo._geoip_resolver.record_by_addr(request.httprequest.remote_addr) or {} + record = odoo._geoip_resolver.resolve(request.httprequest.remote_addr) or {} request.session['geoip'] = record @classmethod diff --git a/odoo/tools/config.py b/odoo/tools/config.py index 5056ae778807577c8500ea5f5154c3b6b8ecc3ea..2bf198cc58531426c99819eebbd044c31b4967e9 100644 --- a/odoo/tools/config.py +++ b/odoo/tools/config.py @@ -255,7 +255,7 @@ class configmanager(object): type="int") group.add_option("--unaccent", dest="unaccent", my_default=False, action="store_true", help="Use the unaccent function provided by the database when available.") - group.add_option("--geoip-db", dest="geoip_database", my_default='/usr/share/GeoIP/GeoLiteCity.dat', + group.add_option("--geoip-db", dest="geoip_database", my_default='/usr/share/GeoIP/GeoLite2-City.mmdb', help="Absolute path to the GeoIP database file.") parser.add_option_group(group)