Limit subdivision types on address
issue7554 review49501002
This commit is contained in:
1 parent
3ce57dbaa8
commit
74457703e5
8 files changed
+185
-8
No files matched your search
@@ -1,3 +1,4 @@
|
||||
* Limit subdivision types on address
|
||||
* Add call url for mobile contact mechanisms
|
||||
* Replace country and language in address format by codes
|
||||
* Add sequence field to contact mechanism form view
|
||||
|
||||
@@ -21,6 +21,7 @@ def register():
|
||||
party.PartyEraseAsk,
|
||||
address.Address,
|
||||
address.AddressFormat,
|
||||
address.SubdivisionType,
|
||||
contact_mechanism.ContactMechanism,
|
||||
configuration.Configuration,
|
||||
configuration.ConfigurationSequence,
|
||||
|
||||
+87
-7
@@ -5,12 +5,12 @@ from string import Template
|
||||
|
||||
from sql.conditionals import Coalesce
|
||||
from sql.functions import Substring
|
||||
from sql.operators import Concat
|
||||
from sql.operators import Concat, Equal
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import (
|
||||
ModelView, ModelSQL, MatchMixin, DeactivableMixin, fields,
|
||||
sequence_ordered)
|
||||
sequence_ordered, Exclude)
|
||||
from trytond.model.exceptions import AccessError
|
||||
from trytond.pyson import Eval, If
|
||||
from trytond.pool import Pool
|
||||
@@ -19,8 +19,6 @@ from trytond.transaction import Transaction
|
||||
from trytond.cache import Cache
|
||||
from .exceptions import InvalidFormat
|
||||
|
||||
__all__ = ['Address', 'AddressFormat']
|
||||
|
||||
STATES = {
|
||||
'readonly': ~Eval('active'),
|
||||
}
|
||||
@@ -44,12 +42,21 @@ class Address(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView):
|
||||
city = fields.Char('City', states=STATES, depends=DEPENDS)
|
||||
country = fields.Many2One('country.country', 'Country',
|
||||
states=STATES, depends=DEPENDS)
|
||||
subdivision_types = fields.Function(
|
||||
fields.MultiSelection(
|
||||
'get_subdivision_types', "Subdivision Types"),
|
||||
'on_change_with_subdivision_types')
|
||||
subdivision = fields.Many2One("country.subdivision",
|
||||
'Subdivision', domain=[
|
||||
'Subdivision',
|
||||
domain=[
|
||||
('country', '=', Eval('country', -1)),
|
||||
('parent', '=', None),
|
||||
If(Eval('subdivision_types', []),
|
||||
('type', 'in', Eval('subdivision_types', [])),
|
||||
()
|
||||
),
|
||||
],
|
||||
states=STATES, depends=['active', 'country'])
|
||||
states=STATES,
|
||||
depends=['active', 'country', 'subdivision_types'])
|
||||
full_address = fields.Function(fields.Text('Full Address'),
|
||||
'get_full_address')
|
||||
|
||||
@@ -221,6 +228,18 @@ class Address(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView):
|
||||
and self.subdivision.country != self.country):
|
||||
self.subdivision = None
|
||||
|
||||
@classmethod
|
||||
def get_subdivision_types(cls):
|
||||
pool = Pool()
|
||||
Subdivision = pool.get('country.subdivision')
|
||||
return Subdivision.fields_get(['type'])['type']['selection']
|
||||
|
||||
@fields.depends('country')
|
||||
def on_change_with_subdivision_types(self, name=None):
|
||||
pool = Pool()
|
||||
Types = pool.get('party.address.subdivision_type')
|
||||
return Types.get_types(self.country)
|
||||
|
||||
|
||||
class AddressFormat(DeactivableMixin, MatchMixin, ModelSQL, ModelView):
|
||||
"Address Format"
|
||||
@@ -349,3 +368,64 @@ ${COUNTRY}"""
|
||||
|
||||
cls._get_format_cache.set(key, format_)
|
||||
return format_
|
||||
|
||||
|
||||
class SubdivisionType(DeactivableMixin, ModelSQL, ModelView):
|
||||
"Address Subdivision Type"
|
||||
__name__ = 'party.address.subdivision_type'
|
||||
country_code = fields.Char("Country Code", size=2, required=True)
|
||||
types = fields.MultiSelection('get_subdivision_types', "Subdivision Types")
|
||||
_get_types_cache = Cache('party.address.subdivision_type.get_types')
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
t = cls.__table__()
|
||||
cls._sql_constraints = [
|
||||
('country_code_unique',
|
||||
Exclude(t, (t.country_code, Equal),
|
||||
where=t.active == True),
|
||||
'party.msg_address_subdivision_country_code_unique')
|
||||
]
|
||||
cls._order.insert(0, ('country_code', 'ASC NULLS LAST'))
|
||||
|
||||
@classmethod
|
||||
def get_subdivision_types(cls):
|
||||
pool = Pool()
|
||||
Subdivision = pool.get('country.subdivision')
|
||||
return Subdivision.fields_get(['type'])['type']['selection']
|
||||
|
||||
@classmethod
|
||||
def create(cls, *args, **kwargs):
|
||||
records = super().create(*args, **kwargs)
|
||||
cls._get_types_cache.clear()
|
||||
return records
|
||||
|
||||
@classmethod
|
||||
def write(cls, *args, **kwargs):
|
||||
super().write(*args, **kwargs)
|
||||
cls._get_types_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def delete(cls, *args, **kwargs):
|
||||
super().delete(*args, **kwargs)
|
||||
cls._get_types_cache.clear()
|
||||
|
||||
@classmethod
|
||||
def get_types(cls, country):
|
||||
key = country.code if country else None
|
||||
types = cls._get_types_cache.get(key)
|
||||
if types is not None:
|
||||
return list(types)
|
||||
|
||||
records = cls.search([
|
||||
('country_code', '=', country.code if country else None),
|
||||
])
|
||||
if records:
|
||||
record, = records
|
||||
types = record.types
|
||||
else:
|
||||
types = []
|
||||
|
||||
cls._get_types_cache.set(key, types)
|
||||
return types
|
||||
+70
-1
@@ -85,6 +85,51 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<field name="perm_delete" eval="True"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="address_subdivision_type_view_list">
|
||||
<field name="model">party.address.subdivision_type</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="name">address_subdivision_type_list</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="address_subdivision_type_view_form">
|
||||
<field name="model">party.address.subdivision_type</field>
|
||||
<field name="type">form</field>
|
||||
<field name="name">address_subdivision_type_form</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.action.act_window" id="act_address_subdivision_type_form">
|
||||
<field name="name">Address Subdivision Types</field>
|
||||
<field name="res_model">party.address.subdivision_type</field>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_address_subdivision_type_form_view1">
|
||||
<field name="sequence" eval="10"/>
|
||||
<field name="view" ref="address_subdivision_type_view_list"/>
|
||||
<field name="act_window" ref="act_address_subdivision_type_form"/>
|
||||
</record>
|
||||
<record model="ir.action.act_window.view" id="act_address_subdivision_type_form_view2">
|
||||
<field name="sequence" eval="20"/>
|
||||
<field name="view" ref="address_subdivision_type_view_form"/>
|
||||
<field name="act_window" ref="act_address_subdivision_type_form"/>
|
||||
</record>
|
||||
<menuitem parent="menu_configuration" sequence="20"
|
||||
action="act_address_subdivision_type_form" id="menu_address_subdivision_type_form"/>
|
||||
|
||||
<record model="ir.model.access" id="access_address_subdivision_type">
|
||||
<field name="model" search="[('model', '=', 'party.address.subdivision_type')]"/>
|
||||
<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_address_subdivision_type_admin">
|
||||
<field name="model" search="[('model', '=', 'party.address.subdivision_type')]"/>
|
||||
<field name="group" ref="group_party_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>
|
||||
<data noupdate="1" grouped="1">
|
||||
<!-- From https://en.wikipedia.org/wiki/Address_(geography) -->
|
||||
@@ -159,6 +204,16 @@ ${zip}
|
||||
${COUNTRY}</field>
|
||||
</record>
|
||||
|
||||
<record model="party.address.format" id="address_format_bg">
|
||||
<field name="country_code">BG</field>
|
||||
<field name="format_">${party_name}
|
||||
${street}
|
||||
${name}
|
||||
${zip} ${city}
|
||||
${subdivision}
|
||||
${COUNTRY}</field>
|
||||
</record>
|
||||
|
||||
<record model="party.address.format" id="address_format_ca_fr">
|
||||
<field name="country_code">CA</field>
|
||||
<field name="language_code">fr</field>
|
||||
@@ -322,6 +377,11 @@ ${subdivision}
|
||||
${COUNTRY}</field>
|
||||
</record>
|
||||
|
||||
<record model="party.address.subdivision_type" id="address_subdivision_type_id">
|
||||
<field name="country_code">ID</field>
|
||||
<field name="types" eval="['province', 'autonomous province', 'special district', 'special region']"/>
|
||||
</record>
|
||||
|
||||
<record model="party.address.format" id="address_format_ir">
|
||||
<field name="country_code">IR</field>
|
||||
<field name="format_">${party_name}
|
||||
@@ -369,6 +429,11 @@ ${zip} ${city} ${SUBDIVISION_CODE}
|
||||
${COUNTRY}</field>
|
||||
</record>
|
||||
|
||||
<record model="party.address.subdivision_type" id="address_subdivision_it">
|
||||
<field name="country_code">IT</field>
|
||||
<field name="types" eval="['province']"/>
|
||||
</record>
|
||||
|
||||
<record model="party.address.format" id="address_format_jp_jp">
|
||||
<field name="country_code">JP</field>
|
||||
<field name="language_code">jp</field>
|
||||
@@ -608,6 +673,11 @@ ${subdivision}
|
||||
${COUNTRY}</field>
|
||||
</record>
|
||||
|
||||
<record model="party.address.subdivision_type" id="address_subdivision_es">
|
||||
<field name="country_code">ES</field>
|
||||
<field name="types" eval="['province']"/>
|
||||
</record>
|
||||
|
||||
<record model="party.address.format" id="address_format_lk">
|
||||
<field name="country_code">LK</field>
|
||||
<field name="format_">${party_name}
|
||||
@@ -706,6 +776,5 @@ ${city}
|
||||
${subdivision}
|
||||
${COUNTRY}</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -51,6 +51,11 @@ Address Format
|
||||
It allows to define per country and language, how addresses should be
|
||||
formatted.
|
||||
|
||||
Address Subdivision Type
|
||||
************************
|
||||
|
||||
It allows to define for each country which types of subdivision are allowed on
|
||||
the address.
|
||||
|
||||
Contact Mechanism
|
||||
*****************
|
||||
|
||||
@@ -36,5 +36,8 @@ this repository contains the full copyright notices and license terms. -->
|
||||
<record model="ir.message" id="msg_category_name_unique">
|
||||
<field name="text">The name of party category must be unique by parent.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_address_subdivision_country_code_unique">
|
||||
<field name="text">The country code on subdivision type must be unique.</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?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>
|
||||
<label name="country_code"/>
|
||||
<field name="country_code"/>
|
||||
<label name="active"/>
|
||||
<field name="active"/>
|
||||
<separator name="types" colspan="4"/>
|
||||
<field name="types" colspan="4"/>
|
||||
</form>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?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>
|
||||
<field name="country_code"/>
|
||||
<field name="types" expand="1"/>
|
||||
</tree>
|
||||
Reference in new issue
Block a user