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 == Literal(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
class ResourceMixin(ResourceAccessMixin, ModelStorage, ModelView): copy_to_resources = fields.MultiSelection( 'get_copy_to_resources', "Copy to Resources", states={ 'invisible': ~Eval('copy_to_resources_visible'), }, depends=['copy_to_resources_visible']) copy_to_resources_visible = fields.Function( fields.Boolean("Copy to Resources Visible"), 'on_change_with_copy_to_resources_visible') last_user = fields.Function( fields.Char('Last User', states={ 'invisible': ~Eval('last_user'), }), 'get_last_user') last_modification = fields.Function( fields.DateTime('Last Modification', states={ 'invisible': ~Eval('last_modification'), }), 'get_last_modification') @classmethod def __setup__(cls): super(ResourceMixin, cls).__setup__() cls._order.insert(0, ('last_modification', 'DESC')) cls.resource.required = True @fields.depends('resource') def get_copy_to_resources(self): pool = Pool() Model = pool.get('ir.model') resources = [] if isinstance(self.resource, ResourceCopyMixin): models = self.resource.get_resources_to_copy(self.__name__) if models: models = Model.search([ ('model', 'in', models), ]) resources.extend((m.model, m.name) for m in models) return resources @fields.depends(methods=['get_copy_to_resources']) def on_change_with_copy_to_resources_visible(self, name=None): return bool(self.get_copy_to_resources()) def get_last_user(self, name): return (self.write_uid.rec_name if self.write_uid else self.create_uid.rec_name) def get_last_modification(self, name): return (self.write_date if self.write_date else self.create_date).replace(microsecond=0) @staticmethod def order_last_modification(tables): table, _ = tables[None] return [Coalesce(table.write_date, table.create_date)]
class Template(metaclass=PoolMeta): __name__ = 'product.template' lot_required = fields.MultiSelection( [ ('supplier', "Supplier"), ('customer', "Customer"), ('lost_found', "Lost and Found"), ('storage', "Storage"), ('production', "Production"), ], "Lot Required", help='The type of location for which lot is required.', states={ 'invisible': ~Eval('type').in_(['goods', 'assets']), }, depends=['type']) @classmethod def __register__(cls, module): connection = Transaction().connection cursor = connection.cursor() super().__register__(module) table_h = cls.__table_handler__(module) template_lot_type_table_name = config.get( 'table', 'product.template-stock.lot.type', default='product.template-stock.lot.type'.replace('.', '_')) lot_type_table_name = config.get('table', 'stock.lot.type', default='stock.lot.type'.replace( '.', '_')) # Migration from 5.2: fill lot_required if (table_h.table_exist(template_lot_type_table_name) and table_h.table_exist(lot_type_table_name)): table = cls.__table__() template_lot_type = Table(template_lot_type_table_name) lot_type = Table(lot_type_table_name) cursor_select = connection.cursor() cursor_select.execute(*template_lot_type.select( template_lot_type.template, distinct_on=template_lot_type.template)) for template_id, in cursor_select: cursor.execute(*template_lot_type.join( lot_type, condition=template_lot_type.type == lot_type.id ).select(lot_type.code, where=template_lot_type.template == template_id)) value = cls.lot_required.sql_format([t for t, in cursor]) cursor.execute(*table.update([table.lot_required], [value], where=table.id == template_id)) table_h.drop_table('product.template-stock.lot.type', template_lot_type_table_name) table_h.drop_table('stock.lot.type', lot_type_table_name)
class ModelStorageEvalEnvironment(ModelStorage_): "Model for EvalEnvironment" __name__ = 'test.modelstorage.eval_environment' char = fields.Char("Name") reference = fields.Reference("Reference", [ ('test.modelstorage.eval_environment', "Reference"), ]) multiselection = fields.MultiSelection([ ('value1', "Value1"), ('value2', "Value2"), ], "MultiSelection") many2one = fields.Many2One('test.modelstorage.eval_environment', "Many2One") one2many = fields.One2Many('test.modelstorage.eval_environment', 'many2one', "One2Many")
class MultiSelection(ModelSQL): 'MultiSelection' __name__ = 'test.multi_selection' selects = fields.MultiSelection([ ('foo', "Foo"), ('bar', "Bar"), ('foobar', "FooBar"), ], "Selections") selects_string = selects.translated('selects') dyn_selects = fields.MultiSelection('get_dyn_selection', "Dynamic Selections") static_selects = fields.MultiSelection('get_static_selection', "Static Selectsions") @fields.depends('selects') def get_dyn_selection(self): if self.selects and 'foo' in self.selects: return [('foo', "Foo"), ('foobar', "FooBar")] else: return [('bar', "Bar"), ('baz', "Baz")] @classmethod def get_static_selection(cls): return cls.selects.selection
class ModelViewChangedValues(ModelView): 'ModelView Changed Values' __name__ = 'test.modelview.changed_values' name = fields.Char('Name') target = fields.Many2One('test.modelview.changed_values.target', 'Target') stored_target = fields.Many2One( 'test.modelview.changed_values.stored_target', "Stored Target") ref_target = fields.Reference('Target Reference', [ ('test.modelview.changed_values.target', 'Target'), ]) targets = fields.One2Many('test.modelview.changed_values.target', 'parent', 'Targets') m2m_targets = fields.Many2Many('test.modelview.changed_values.target', None, None, 'Targets') multiselection = fields.MultiSelection([ ('a', 'A'), ('b', 'B'), ], "MultiSelection") dictionary = fields.Dict('test.modelview.changed_values.dictionary', "Dictionary")
class WorkStatus(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView): 'Work Status' __name__ = 'project.work.status' _get_default_status_cache = Cache('project_work_status.get_default_status') _get_window_domains_cache = Cache('project_work_status.get_window_domains') types = fields.MultiSelection( 'get_types', "Types", help="The type of works which can use this status.") name = fields.Char("Name", required=True, translate=True) progress = fields.Float( "Progress", domain=['OR', ('progress', '=', None), [ ('progress', '>=', 0), ('progress', '<=', 1), ], ], help="The minimum progress required for this status.") default = fields.Boolean( "Default", help="Check to use as default status for the type.") count = fields.Boolean( "Count", help="Check to show the number of works in this status.") @classmethod def get_types(cls): pool = Pool() Work = pool.get('project.work') return Work.fields_get(['type'])['type']['selection'] @classmethod def get_default_status(cls, type_=None): if type_ is None: return None status = cls._get_default_status_cache.get(type_, -1) if status != -1: return status records = cls.search([ ('types', 'in', type_), ('default', '=', True) ], limit=1) if records: status = records[0].id else: status = None cls._get_default_status_cache.set(type, status) return status @classmethod def create(cls, vlist): cls._get_default_status_cache.clear() cls._get_window_domains_cache.clear() return super().create(vlist) @classmethod def write(cls, *args): super().write(*args) cls._get_default_status_cache.clear() cls._get_window_domains_cache.clear() @classmethod def delete(cls, status): cls._get_default_status_cache.clear() cls._get_window_domains_cache.clear() super().delete(status) @classmethod def get_window_domains(cls, action): pool = Pool() Data = pool.get('ir.model.data') if action.id == Data.get_id('project', 'act_project_tree'): return cls._get_window_domains([x[0] for x in cls.get_types()]) elif action.id == Data.get_id('project', 'act_project_form'): return cls._get_window_domains(['project']) elif action.id == Data.get_id('project', 'act_task_form'): return cls._get_window_domains(['task']) else: return [] @classmethod def _get_window_domains(cls, types): key = tuple(sorted(types)) domains = cls._get_window_domains_cache.get(key) if domains is not None: return domains encoder = PYSONEncoder() domains = [] for status in cls.search([('types', 'in', types)]): domain = encoder.encode([('status', '=', status.id)]) domains.append((status.name, domain, status.count)) if domains: domains.append( (gettext('project.msg_domain_all'), '[]', False)) cls._get_window_domains_cache.set(key, domains) return domains
class Configuration(ModelSingleton, ModelSQL, ModelView, MultiValueMixin): 'Party Configuration' __name__ = 'party.configuration' party_sequence = fields.MultiValue(party_sequence) party_lang = fields.MultiValue(party_lang) identifier_types = fields.MultiSelection( IDENTIFIER_TYPES, "Identifier Types", help="Defines which identifier types are available.\n" "Leave empty for all of them.") @classmethod def default_party_sequence(cls, **pattern): pool = Pool() ModelData = pool.get('ir.model.data') try: return ModelData.get_id('party', 'sequence_party') except KeyError: return None def get_identifier_types(self): selection = self.fields_get(['identifier_types' ])['identifier_types']['selection'] if self.identifier_types: selection = [(k, v) for k, v in selection if k in self.identifier_types] return selection @classmethod def create(cls, vlist): records = super().create(vlist) ModelView._fields_view_get_cache.clear() return records @classmethod def write(cls, *args): super().write(*args) ModelView._fields_view_get_cache.clear() @classmethod def delete(cls, records): super().delete(records) ModelView._fields_view_get_cache.clear() @classmethod def validate(cls, records): super().validate(records) cls(1).check_identifier_types() def check_identifier_types(self): pool = Pool() Identifier = pool.get('party.identifier') if self.identifier_types: identifiers = Identifier.search([ ('type', 'not in', [None, ''] + self.identifier_types), ], limit=1, order=[]) if identifiers: identifier, = identifiers selection = self.fields_get( ['identifier_types'])['identifier_types']['selection'] selection = dict(selection) raise AccessError( gettext( 'party.msg_identifier_type_remove', type=selection.get(identifier.type, identifier.type), identifier=identifier.rec_name, ))
class Address(DeactivableMixin, sequence_ordered(), ModelSQL, ModelView): "Address" __name__ = 'party.address' party = fields.Many2One('party.party', 'Party', required=True, ondelete='CASCADE', select=True, states={ 'readonly': If(~Eval('active'), True, Eval('id', 0) > 0), }, depends=['active', 'id']) party_name = fields.Char( "Party Name", states=STATES, depends=DEPENDS, help="If filled, replace the name of the party for address formatting") name = fields.Char("Building Name", states=STATES, depends=DEPENDS) street = fields.Text("Street", states=STATES, depends=DEPENDS) zip = fields.Char('Zip', states=STATES, depends=DEPENDS) 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=[ ('country', '=', Eval('country', -1)), If(Eval('subdivision_types', []), ('type', 'in', Eval('subdivision_types', [])), ()), ], states=STATES, depends=['active', 'country', 'subdivision_types']) full_address = fields.Function(fields.Text('Full Address'), 'get_full_address') @classmethod def __setup__(cls): super(Address, cls).__setup__() cls._order.insert(0, ('party', 'ASC')) cls.__rpc__.update( autocomplete_zip=RPC(instantiate=0, cache=dict(days=1)), autocomplete_city=RPC(instantiate=0, cache=dict(days=1)), ) @classmethod def __register__(cls, module_name): cursor = Transaction().connection.cursor() sql_table = cls.__table__() super(Address, cls).__register__(module_name) table = cls.__table_handler__(module_name) # Migration from 4.0: remove streetbis if table.column_exist('streetbis'): value = Concat(Coalesce(sql_table.street, ''), Concat('\n', Coalesce(sql_table.streetbis, ''))) cursor.execute(*sql_table.update([sql_table.street], [value])) table.drop_column('streetbis') _autocomplete_limit = 100 @fields.depends('country', 'subdivision') def _autocomplete_domain(self): domain = [] if self.country: domain.append(('country', '=', self.country.id)) if self.subdivision: domain.append([ 'OR', ('subdivision', 'child_of', [self.subdivision.id], 'parent'), ('subdivision', '=', None), ]) return domain def _autocomplete_search(self, domain, name): pool = Pool() Zip = pool.get('country.zip') if domain: records = Zip.search(domain, limit=self._autocomplete_limit) if len(records) < self._autocomplete_limit: return sorted({getattr(z, name) for z in records}) return [] @fields.depends('city', methods=['_autocomplete_domain']) def autocomplete_zip(self): domain = self._autocomplete_domain() if self.city: domain.append(('city', 'ilike', '%%%s%%' % self.city)) return self._autocomplete_search(domain, 'zip') @fields.depends('zip', methods=['_autocomplete_domain']) def autocomplete_city(self): domain = self._autocomplete_domain() if self.zip: domain.append(('zip', 'ilike', '%s%%' % self.zip)) return self._autocomplete_search(domain, 'city') def get_full_address(self, name): pool = Pool() AddressFormat = pool.get('party.address.format') full_address = Template(AddressFormat.get_format(self)).substitute( **self._get_address_substitutions()) return '\n'.join( filter(None, (x.strip() for x in full_address.splitlines()))) def _get_address_substitutions(self): context = Transaction().context subdivision_code = '' if getattr(self, 'subdivision', None): subdivision_code = self.subdivision.code or '' if '-' in subdivision_code: subdivision_code = subdivision_code.split('-', 1)[1] substitutions = { 'party_name': '', 'attn': '', 'name': getattr(self, 'name', None) or '', 'street': getattr(self, 'street', None) or '', 'zip': getattr(self, 'zip', None) or '', 'city': getattr(self, 'city', None) or '', 'subdivision': (self.subdivision.name if getattr( self, 'subdivision', None) else ''), 'subdivision_code': subdivision_code, 'country': (self.country.name if getattr(self, 'country', None) else ''), 'country_code': (self.country.code or '' if getattr( self, 'country', None) else ''), } if context.get('address_from_country') == getattr(self, 'country', ''): substitutions['country'] = '' if context.get('address_with_party', False): substitutions['party_name'] = self.party_full_name if context.get('address_attention_party', False): substitutions['attn'] = ( context['address_attention_party'].full_name) for key, value in list(substitutions.items()): substitutions[key.upper()] = value.upper() return substitutions @property def party_full_name(self): name = '' if self.party_name: name = self.party_name elif self.party: name = self.party.full_name return name def get_rec_name(self, name): party = self.party_full_name if self.street: street = self.street.splitlines()[0] else: street = None if self.country: country = self.country.code else: country = None return ', '.join( filter(None, [party, self.name, street, self.zip, self.city, country])) @classmethod def search_rec_name(cls, name, clause): if clause[1].startswith('!') or clause[1].startswith('not '): bool_op = 'AND' else: bool_op = 'OR' return [ bool_op, ('party', ) + tuple(clause[1:]), ('name', ) + tuple(clause[1:]), ('street', ) + tuple(clause[1:]), ('zip', ) + tuple(clause[1:]), ('city', ) + tuple(clause[1:]), ('country', ) + tuple(clause[1:]), ] @classmethod def write(cls, *args): actions = iter(args) for addresses, values in zip(actions, actions): if 'party' in values: for address in addresses: if address.party.id != values['party']: raise AccessError( gettext('party.msg_address_change_party', address=address.rec_name)) super(Address, cls).write(*args) @fields.depends('subdivision', 'country') def on_change_country(self): if (self.subdivision 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 LabWorkYear(ModelSQL, ModelView, CompanyMultiValueMixin): 'Work Year' __name__ = 'lims.lab.workyear' _rec_name = 'code' code = fields.Char('Code', required=True) start_date = fields.Date('Start date', required=True) end_date = fields.Date('End date', required=True) entry_sequence = fields.MultiValue( fields.Many2One('ir.sequence', 'Entry Sequence', required=True, domain=[ ('sequence_type', '=', Id('lims', 'seq_type_entry')), ('company', 'in', [Eval('context', {}).get('company', -1), None]), ])) sample_sequence = fields.MultiValue( fields.Many2One('ir.sequence', 'Sample Sequence', required=True, domain=[ ('sequence_type', '=', Id('lims', 'seq_type_sample')), ('company', 'in', [Eval('context', {}).get('company', -1), None]), ])) service_sequence = fields.MultiValue( fields.Many2One('ir.sequence', 'Service Sequence', required=True, domain=[ ('sequence_type', '=', Id('lims', 'seq_type_service')), ('company', 'in', [Eval('context', {}).get('company', -1), None]), ])) results_report_sequence = fields.MultiValue( fields.Many2One('ir.sequence', 'Results Report Sequence', required=True, domain=[ ('sequence_type', '=', Id('lims', 'seq_type_results_report')), ('company', 'in', [Eval('context', {}).get('company', -1), None]), ])) sequences = fields.One2Many('lims.lab.workyear.sequence', 'workyear', 'Sequences') default_entry_control = fields.Many2One('lims.entry', 'Default entry control') workdays = fields.MultiSelection([ (0, 'Monday'), (1, 'Tuesday'), (2, 'Wednesday'), (3, 'Thursday'), (4, 'Friday'), (5, 'Saturday'), (6, 'Sunday'), ], 'Working days', sort=False) holidays = fields.One2Many('lims.lab.workyear.holiday', 'workyear', 'Holidays') @classmethod def __setup__(cls): super().__setup__() cls._order.insert(0, ('start_date', 'ASC')) @classmethod def multivalue_model(cls, field): pool = Pool() if field in sequence_names: return pool.get('lims.lab.workyear.sequence') return super().multivalue_model(field) @classmethod def default_entry_sequence(cls, **pattern): return cls.multivalue_model('entry_sequence').default_entry_sequence() @classmethod def default_sample_sequence(cls, **pattern): return cls.multivalue_model( 'sample_sequence').default_sample_sequence() @classmethod def default_service_sequence(cls, **pattern): return cls.multivalue_model( 'service_sequence').default_service_sequence() @staticmethod def default_workdays(): return (0, 1, 2, 3, 4) @classmethod def validate(cls, years): super().validate(years) for year in years: year.check_dates() def check_dates(self): cursor = Transaction().connection.cursor() table = self.__table__() cursor.execute( *table.select(table.id, where=(((table.start_date <= self.start_date) & (table.end_date >= self.start_date)) | ( (table.start_date <= self.end_date) & (table.end_date >= self.end_date)) | ( (table.start_date >= self.start_date) & (table.end_date <= self.end_date))) & (table.id != self.id))) second_id = cursor.fetchone() if second_id: second = self.__class__(second_id[0]) raise UserError( gettext( 'lims.msg_workyear_overlaps', first=self.rec_name, second=second.rec_name, )) @classmethod def find(cls, date=None, exception=True): pool = Pool() Lang = pool.get('ir.lang') Date = pool.get('ir.date') if not date: date = Date.today() workyears = cls.search([ ('start_date', '<=', date), ('end_date', '>=', date), ], order=[('start_date', 'DESC')], limit=1) if not workyears: if exception: lang = Lang.get() formatted = lang.strftime(date) raise UserError( gettext('lims.msg_no_workyear_date', date=formatted)) else: return None return workyears[0].id def get_sequence(self, type): sequence = getattr(self, type + '_sequence') if sequence: return sequence def get_target_date(self, start_date, days): total_days = days + 1 # plus 1 because start_date is included ruleset = rrule.rruleset() min_time = datetime.min.time() for h in self.holidays: ruleset.exdate(datetime.combine(h.date, min_time)) count = total_days ruleset.rrule( rrule.rrule(rrule.DAILY, byweekday=self.workdays, dtstart=start_date, count=count)) while (ruleset.count() < total_days): # because holidays subtract days count += 1 ruleset.rrule( rrule.rrule(rrule.DAILY, byweekday=self.workdays, dtstart=start_date, count=count)) return ruleset[-1].date()
class MultiSelectionRequired(ModelSQL): "MultiSelection Required" __name__ = 'test.multi_selection_required' selects = fields.MultiSelection([('foo', "Foo"), ('bar', "Bar")], "Selects", required=True)
class Template(metaclass=PoolMeta): __name__ = 'product.template' lot_required = fields.MultiSelection( [ ('supplier', "Supplier"), ('customer', "Customer"), ('lost_found', "Lost and Found"), ('storage', "Storage"), ('production', "Production"), ], "Lot Required", help='The type of location for which lot is required.', states={ 'invisible': ~Eval('type').in_(['goods', 'assets']), }) lot_sequence = fields.Many2One( 'ir.sequence', "Lot Sequence", domain=[ ('sequence_type', '=', Id('stock_lot', 'sequence_type_stock_lot')), ], states={ 'invisible': ~Eval('type').in_(['goods', 'assets']), }, help="The sequence used to automatically number lots.") @classmethod def __register__(cls, module): connection = Transaction().connection cursor = connection.cursor() super().__register__(module) table_h = cls.__table_handler__(module) template_lot_type_table_name = config.get( 'table', 'product.template-stock.lot.type', default='product.template-stock.lot.type'.replace('.', '_')) lot_type_table_name = config.get('table', 'stock.lot.type', default='stock.lot.type'.replace( '.', '_')) # Migration from 5.2: fill lot_required if (table_h.table_exist(template_lot_type_table_name) and table_h.table_exist(lot_type_table_name)): table = cls.__table__() template_lot_type = Table(template_lot_type_table_name) lot_type = Table(lot_type_table_name) cursor_select = connection.cursor() cursor_select.execute(*template_lot_type.select( template_lot_type.template, distinct_on=template_lot_type.template)) for template_id, in cursor_select: cursor.execute(*template_lot_type.join( lot_type, condition=template_lot_type.type == lot_type.id ).select(lot_type.code, where=template_lot_type.template == template_id)) value = cls.lot_required.sql_format([t for t, in cursor]) cursor.execute(*table.update([table.lot_required], [value], where=table.id == template_id)) table_h.drop_table('product.template-stock.lot.type', template_lot_type_table_name) table_h.drop_table('stock.lot.type', lot_type_table_name) @classmethod def default_lot_sequence(cls, **pattern): pool = Pool() Configuration = pool.get('product.configuration') sequence = Configuration(1).get_multivalue('default_lot_sequence', **pattern) return sequence.id if sequence else None
class PerformVisitAddress(ModelView): "Perform Visit Address" __name__ = 'sale.direct.visit.perform.address' new_address = fields.Boolean("New Address") address = fields.Many2One('party.address', "Address", states={ 'invisible': Eval('new_address', False), }, depends=['new_address']) _states = { 'invisible': ~Eval('new_address'), } _depends = ['new_address'] name = fields.Char("Building Name", states={ 'invisible': ~Eval('new_address', False), 'required': Eval('new_address', False), }, depends=_depends) street = fields.Text("Street", states=_states, depends=_depends) postal_code = fields.Char("Postal Code", states=_states, depends=_depends) 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", states=_states, depends=_depends), 'on_change_with_subdivision_types') subdivision = fields.Many2One( 'country.subdivision', "Subdivision", domain=[ ('country', '=', Eval('country', -1)), If(Eval('subdivision_types', []), ('type', 'in', Eval('subdivision_types', [])), ()), ], states=_states, depends=_depends + ['country', 'subdivision_types']) del _states, _depends @fields.depends('subdivision', 'country') def on_change_country(self): if (self.subdivision 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)