summaryrefslogtreecommitdiff
path: root/addons/base_address_city/models
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/base_address_city/models
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/base_address_city/models')
-rw-r--r--addons/base_address_city/models/__init__.py6
-rw-r--r--addons/base_address_city/models/res_city.py16
-rw-r--r--addons/base_address_city/models/res_country.py13
-rw-r--r--addons/base_address_city/models/res_partner.py91
4 files changed, 126 insertions, 0 deletions
diff --git a/addons/base_address_city/models/__init__.py b/addons/base_address_city/models/__init__.py
new file mode 100644
index 00000000..7d7f5d58
--- /dev/null
+++ b/addons/base_address_city/models/__init__.py
@@ -0,0 +1,6 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import res_city
+from . import res_country
+from . import res_partner
diff --git a/addons/base_address_city/models/res_city.py b/addons/base_address_city/models/res_city.py
new file mode 100644
index 00000000..c542a1a3
--- /dev/null
+++ b/addons/base_address_city/models/res_city.py
@@ -0,0 +1,16 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class City(models.Model):
+ _name = 'res.city'
+ _description = 'City'
+ _order = 'name'
+
+ name = fields.Char("Name", required=True, translate=True)
+ zipcode = fields.Char("Zip")
+ country_id = fields.Many2one('res.country', string='Country', required=True)
+ state_id = fields.Many2one(
+ 'res.country.state', 'State', domain="[('country_id', '=', country_id)]")
diff --git a/addons/base_address_city/models/res_country.py b/addons/base_address_city/models/res_country.py
new file mode 100644
index 00000000..a3de7de6
--- /dev/null
+++ b/addons/base_address_city/models/res_country.py
@@ -0,0 +1,13 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo import fields, models
+
+
+class Country(models.Model):
+ _inherit = 'res.country'
+
+ enforce_cities = fields.Boolean(
+ string='Enforce Cities',
+ help="Check this box to ensure every address created in that country has a 'City' chosen "
+ "in the list of the country's cities.")
diff --git a/addons/base_address_city/models/res_partner.py b/addons/base_address_city/models/res_partner.py
new file mode 100644
index 00000000..f49d3e43
--- /dev/null
+++ b/addons/base_address_city/models/res_partner.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from lxml import etree
+
+from odoo import api, models, fields
+from odoo.tools.translate import _
+
+
+class Partner(models.Model):
+ _inherit = 'res.partner'
+
+ country_enforce_cities = fields.Boolean(related='country_id.enforce_cities', readonly=True)
+ city_id = fields.Many2one('res.city', string='City of Address')
+
+ @api.onchange('city_id')
+ def _onchange_city_id(self):
+ if self.city_id:
+ self.city = self.city_id.name
+ self.zip = self.city_id.zipcode
+ self.state_id = self.city_id.state_id
+ elif self._origin:
+ self.city = False
+ self.zip = False
+ self.state_id = False
+
+ @api.model
+ def _fields_view_get_address(self, arch):
+ arch = super(Partner, self)._fields_view_get_address(arch)
+ # render the partner address accordingly to address_view_id
+ doc = etree.fromstring(arch)
+ if doc.xpath("//field[@name='city_id']"):
+ return arch
+
+ replacement_xml = """
+ <div>
+ <field name="country_enforce_cities" invisible="1"/>
+ <field name="parent_id" invisible="1"/>
+ <field name='city' placeholder="%(placeholder)s" class="o_address_city"
+ attrs="{
+ 'invisible': [('country_enforce_cities', '=', True), '|', ('city_id', '!=', False), ('city', 'in', ['', False ])],
+ 'readonly': [('type', '=', 'contact')%(parent_condition)s]
+ }"
+ />
+ <field name='city_id' placeholder="%(placeholder)s" string="%(placeholder)s" class="o_address_city"
+ context="{'default_country_id': country_id,
+ 'default_name': city,
+ 'default_zipcode': zip,
+ 'default_state_id': state_id}"
+ domain="[('country_id', '=', country_id)]"
+ attrs="{
+ 'invisible': [('country_enforce_cities', '=', False)],
+ 'readonly': [('type', '=', 'contact')%(parent_condition)s]
+ }"
+ />
+ </div>
+ """
+
+ replacement_data = {
+ 'placeholder': _('City'),
+ }
+
+ def _arch_location(node):
+ in_subview = False
+ view_type = False
+ parent = node.getparent()
+ while parent is not None and (not view_type or not in_subview):
+ if parent.tag == 'field':
+ in_subview = True
+ elif parent.tag in ['list', 'tree', 'kanban', 'form']:
+ view_type = parent.tag
+ parent = parent.getparent()
+ return {
+ 'view_type': view_type,
+ 'in_subview': in_subview,
+ }
+
+ for city_node in doc.xpath("//field[@name='city']"):
+ location = _arch_location(city_node)
+ replacement_data['parent_condition'] = ''
+ if location['view_type'] == 'form' or not location['in_subview']:
+ replacement_data['parent_condition'] = ", ('parent_id', '!=', False)"
+
+ replacement_formatted = replacement_xml % replacement_data
+ for replace_node in etree.fromstring(replacement_formatted).getchildren():
+ city_node.addprevious(replace_node)
+ parent = city_node.getparent()
+ parent.remove(city_node)
+
+ arch = etree.tostring(doc, encoding='unicode')
+ return arch