def startElement(self, name, attributes): # Manage the top level tag if name == "record": self.model = self.mh.pool.get(attributes["model"]) assert self.model, "The model %s does not exist !" % \ (attributes["model"],) self.xml_id = attributes["id"] self.update = bool(int(attributes.get('update', '0'))) # create/update a dict containing fields values self.values = {} self.current_field = None self.cdata = False return self.xml_id # Manage included tags: elif name == "field": field_name = attributes['name'] field_type = attributes.get('type', '') # Create a new entry in the values self.values[field_name] = "" # Remind the current name (see characters) self.current_field = field_name # Put a flag to escape cdata tags if field_type == "xml": self.cdata = "start" # Catch the known attributes search_attr = attributes.get('search', '') ref_attr = attributes.get('ref', '') eval_attr = attributes.get('eval', '') if search_attr: search_model = self.model._columns[field_name].model_name f_obj = self.mh.pool.get(search_model) with Transaction().set_context(active_test=False): self.values[field_name], = \ f_obj.search(safe_eval(search_attr)) elif ref_attr: self.values[field_name] = self.mh.get_id(ref_attr) elif eval_attr: context = {} context['time'] = time context['version'] = VERSION.rsplit('.', 1)[0] context['ref'] = self.mh.get_id context['obj'] = lambda *a: 1 self.values[field_name] = safe_eval(eval_attr, context) else: raise Exception("Tags '%s' not supported inside tag record." % (name,))
def _clean_value(key, browse_record, object_ref): """ Take a field name, a browse_record, and a reference to the corresponding object. Return a raw value has it must look on the db. """ # search the field type in the object or in a parent if key in object_ref._columns: field_type = object_ref._columns[key]._type else: field_type = object_ref._inherit_fields[key][2]._type # handle the value regarding to the type if field_type == 'many2one': return browse_record[key] and browse_record[key].id or None elif field_type == 'reference': if not browse_record[key]: return None ref_mode, ref_id = browse_record[key].split(',', 1) try: ref_id = safe_eval(ref_id) except Exception: pass if isinstance(ref_id, (list, tuple)): ref_id = ref_id[0] return ref_mode + ',' + str(ref_id) elif field_type in ['one2many', 'many2many']: raise Unhandled_field("Unhandled field %s" % key) else: return browse_record[key]
def _clean_value(key, record): """ Take a field name, a browse_record, and a reference to the corresponding object. Return a raw value has it must look on the db. """ Model = record.__class__ # search the field type in the object or in a parent field_type = Model._fields[key]._type # handle the value regarding to the type if field_type == 'many2one': return getattr(record, key).id if getattr(record, key) else None elif field_type == 'reference': if not getattr(record, key): return None elif not isinstance(getattr(record, key), basestring): return str(getattr(record, key)) ref_mode, ref_id = getattr(record, key).split(',', 1) try: ref_id = safe_eval(ref_id) except Exception: pass if isinstance(ref_id, (list, tuple)): ref_id = ref_id[0] return ref_mode + ',' + str(ref_id) elif field_type in ['one2many', 'many2many']: raise Unhandled_field("Unhandled field %s" % key) else: return getattr(record, key)
def get_unit_price(self): ''' Return unit price (as Decimal) ''' context = Transaction().context.copy() context['Decimal'] = Decimal return safe_eval(decistmt(self.formula), context)
def init(cursor): from trytond.tools import safe_eval sql_file = os.path.join(os.path.dirname(__file__), 'init.sql') with open(sql_file) as fp: for line in fp.read().split(';'): if (len(line) > 0) and (not line.isspace()): cursor.execute(line) for i in ('ir', 'res', 'webdav'): root_path = os.path.join(os.path.dirname(__file__), '..', '..') tryton_file = os.path.join(root_path, i, '__tryton__.py') with open(tryton_file) as fp: info = safe_eval(fp.read()) active = info.get('active', False) if active: state = 'to install' else: state = 'uninstalled' cursor.execute('INSERT INTO ir_module_module ' \ '(create_uid, create_date, author, website, name, ' \ 'shortdesc, description, state) ' \ 'VALUES (%s, %s, %s, %s, %s, %s, %s, %s)', (0, datetime.datetime.now(), info.get('author', ''), info.get('website', ''), i, info.get('name', False), info.get('description', ''), state)) cursor.execute('SELECT last_insert_rowid()') module_id = cursor.fetchone()[0] dependencies = info.get('depends', []) for dependency in dependencies: cursor.execute('INSERT INTO ir_module_module_dependency ' \ '(create_uid, create_date, module, name) ' \ 'VALUES (%s, %s, %s, %s) ', (0, datetime.datetime.now(), module_id, dependency))
def create_graph(module_list): graph = Graph() packages = [] for module in module_list: tryton_file = OPJ(MODULES_PATH, module, '__tryton__.py') mod_path = OPJ(MODULES_PATH, module) if module in ('ir', 'res', 'webdav', 'test'): root_path = os.path.abspath(os.path.dirname( os.path.dirname(__file__))) tryton_file = OPJ(root_path, module, '__tryton__.py') mod_path = OPJ(root_path, module) elif module in EGG_MODULES: ep = EGG_MODULES[module] tryton_file = OPJ(ep.dist.location, 'trytond', 'modules', module, '__tryton__.py') mod_path = OPJ(ep.dist.location, 'trytond', 'modules', module) if not os.path.isfile(tryton_file) or not os.path.isdir(mod_path): # When testing modules from setuptools location is the module # directory tryton_file = OPJ(ep.dist.location, '__tryton__.py') mod_path = os.path.dirname(ep.dist.location) if os.path.isfile(tryton_file): with tools.file_open(tryton_file, subdir='') as fp: info = tools.safe_eval(fp.read()) packages.append((module, info.get('depends', []), info.get('extras_depend', []), info)) elif module != 'all': raise Exception('Module %s not found' % module) current, later = set([x[0] for x in packages]), set() all_packages = set(current) while packages and current > later: package, deps, xdep, info = packages[0] # if all dependencies of 'package' are already in the graph, # add 'package' in the graph all_deps = deps + [x for x in xdep if x in all_packages] if reduce(lambda x, y: x and y in graph, all_deps, True): if not package in current: packages.pop(0) continue later.clear() current.remove(package) graph.add_node(package, all_deps) node = Node(package, graph) node.info = info else: later.add(package) packages.append((package, deps, xdep, info)) packages.pop(0) for package, deps, xdep, info in packages: if package not in later: continue missings = [x for x in deps if x not in graph] raise Exception('%s unmet dependencies: %s' % (package, missings)) return graph, packages, later
def _engine_python(self, expression, record): '''Evaluate the pythonic expression and return its value ''' if expression is None: return u'' assert record is not None, 'Record is undefined' template_context = self.template_context(record) return safe_eval(expression, template_context)
def get_fields(self, ids, names): if not ids: return {} res={} for line in self.browse(ids): all_add_options = False if line.add_options: all_add_options = safe_eval(line.add_options,{ 'Decimal': Decimal, 'datetime': datetime}) for name in names: res.setdefault(name, {}) res[name].setdefault(line.id, False) if name == 'number_doc': if name == 'number_doc': if line.type_transaction in ('expense', 'expense_tax') : res[name][line.id] = line.number_our else: res[name][line.id] = line.number_in elif name == 'state_doc': res[name][line.id] = line.state elif name == 'from_party_doc': res[name][line.id] = line.from_party.id elif name == 'to_party_doc': res[name][line.id] = line.to_party.id elif name == 'template_bank': res[name][line.id] = line.template.id elif name == 'content': res[name][line.id] = line.note elif all_add_options and name == 'pole_order': res[name][line.id] = all_add_options.get('pole_order') elif all_add_options and name == 'pole_type': res[name][line.id] = all_add_options.get('pole_type') elif all_add_options and name == 'pole_maturity': res[name][line.id] = all_add_options.get('pole_maturity') elif all_add_options and name == 'pole_detail': res[name][line.id] = all_add_options.get('pole_detail') elif all_add_options and name == 'pole_code': res[name][line.id] = all_add_options.get('pole_code') elif all_add_options and name == 'pole_reserve': res[name][line.id] = all_add_options.get('pole_reserve') elif all_add_options and name == 'kind_payment_tax': res[name][line.id] = all_add_options.get('kind_payment_tax') elif all_add_options and name == 'status_payer_tax': res[name][line.id] = all_add_options.get('status_payer_tax') elif all_add_options and name == 'kbk_indicator': res[name][line.id] = all_add_options.get('kbk_indicator') elif all_add_options and name == 'okato_indicator': res[name][line.id] = all_add_options.get('okato_indicator') elif all_add_options and name == 'payment_details_tax': res[name][line.id] = all_add_options.get('payment_details_tax') elif all_add_options and name == 'number_doc_base_tax': res[name][line.id] = all_add_options.get('number_doc_base_tax') elif all_add_options and name == 'tax_period': res[name][line.id] = all_add_options.get('tax_period') return res
def _search_quantity_eval_domain(line, domain): field, operator, operand = domain value = line.get(field) if value is None: return False if operator not in ("=", ">=", "<=", ">", "<", "!="): return False if operator == "=": operator = "==" return (safe_eval(str(value) + operator + str(operand)))
def encode(element): for attr in ('states', 'domain', 'spell', 'colors'): if element.get(attr): try: value = safe_eval(element.get(attr), CONTEXT) validates.get(attr, lambda a: True)(value) except Exception, e: cls.logger.error('Invalid pyson view element "%s:%s":' '\n%s\n%s' % (element.get('id') or element.get('name'), attr, str(e), xml)) return False
def get_module_info(name): "Return the content of the __tryton__.py" try: if name in ['ir', 'res', 'webdav']: file_p = tools.file_open(os.path.join(name, '__tryton__.py')) else: file_p = tools.file_open(os.path.join(name, '__tryton__.py')) with file_p: data = file_p.read() info = tools.safe_eval(data) except Exception: return {} return info
def encode(element): for attr in ("states", "domain", "context", "digits", "add_remove", "spell", "colors"): if element.get(attr): try: value = safe_eval(element.get(attr), CONTEXT) validates.get(attr, lambda a: True)(value) except Exception, e: logger = logging.getLogger("ir") logger.error( 'Invalid pyson view element "%s:%s":' "\n%s\n%s" % (element.get("id") or element.get("name"), attr, str(e), xml) ) return False
def check_mon_grouping(self): ''' Check if mon_grouping is list of numbers ''' try: grouping = safe_eval(self.mon_grouping) for i in grouping: if not isinstance(i, int): raise ValueError except Exception: self.raise_user_error('invalid_mon_grouping', { 'grouping': self.mon_grouping, 'currency': self.rec_name, })
def compute_formula(self, id, formula, values={}): minus = 1 if formula[:1] == '-': minus = -1 formula = formula[1:] if formula == 'AmountDoc': return values['AmountDoc'] * minus elif formula == 'AmountLine': return values['AmountLine'] * minus elif formula == 'AmountAnalytic': return values['AmountAnalytic'] * minus elif formula == 'AmountTax': return values['AmountTax'] * minus #raise Exception(str(values)) context = Transaction().context line_obj = self.pool.get('ekd.account.move.line.template') line = line_obj.browse(id) return safe_eval( formula, { 'turnover': self.turnover, 'balance': self.balance, 'Period': self.period, 'Date': self.date, 'FromParty': line.ct_analytic, 'ToParty': line.dt_analytic, 'AccountDt': line.dt_account.id, 'AccountCt': line.ct_account.id, 'Debit': 1, 'Credit': -1, 'AmountDoc': Decimal('0.0'), 'AmountDocTax': Decimal('0.0'), 'AmountLine': Decimal('0.0'), 'AmountLineTax': Decimal('0.0'), 'AmountAnalytic': Decimal('0.0'), 'AmountFixed': Decimal('0.0'), 'AmountIntagible': Decimal('0.0'), 'AmountMaterial': Decimal('0.0'), 'AmountGoods': Decimal('0.0'), 'AmountSupplier': Decimal('0.0'), 'AmountCustomer': Decimal('0.0'), 'AmountEmployee': Decimal('0.0'), 'CurrentPeriod': context.get('current_period'), 'FiscalYear': context.get('fiscalyear'), 'StartDate': context.get('start_period'), 'EndDate': context.get('end_period'), 'CurrentDate': context.get('current_date'), }.update(values))
def compute_formula(self, id, formula, values={}): minus = 1 if formula[:1] == '-': minus = -1 formula = formula[1:] if formula == 'AmountDoc': return values['AmountDoc']*minus elif formula == 'AmountLine': return values['AmountLine']*minus elif formula == 'AmountAnalytic': return values['AmountAnalytic']*minus elif formula == 'AmountTax': return values['AmountTax']*minus #raise Exception(str(values)) context = Transaction().context line_obj = self.pool.get('ekd.account.move.line.template') line = line_obj.browse(id) return safe_eval(formula, { 'turnover': self.turnover, 'balance': self.balance, 'Period': self.period, 'Date': self.date, 'FromParty': line.ct_analytic, 'ToParty': line.dt_analytic, 'AccountDt': line.dt_account.id, 'AccountCt': line.ct_account.id, 'Debit': 1, 'Credit': -1, 'AmountDoc': Decimal('0.0'), 'AmountDocTax': Decimal('0.0'), 'AmountLine': Decimal('0.0'), 'AmountLineTax': Decimal('0.0'), 'AmountAnalytic': Decimal('0.0'), 'AmountFixed': Decimal('0.0'), 'AmountIntagible': Decimal('0.0'), 'AmountMaterial': Decimal('0.0'), 'AmountGoods': Decimal('0.0'), 'AmountSupplier': Decimal('0.0'), 'AmountCustomer': Decimal('0.0'), 'AmountEmployee': Decimal('0.0'), 'CurrentPeriod': context.get('current_period'), 'FiscalYear': context.get('fiscalyear'), 'StartDate': context.get('start_period'), 'EndDate': context.get('end_period'), 'CurrentDate': context.get('current_date'), }.update(values))
def check_xml_record(self, ids, values): """ Check if a list of records and their corresponding fields are originating from xml data. This is used by write and delete functions: if the return value is True the records can be written/deleted, False otherwise. The default behaviour is to forbid any modification on records/fields originating from xml. Values is the dictionary of written values. If values is equal to None, no field by field check is performed, False is returned as soon as one of the record comes from the xml. :param ids: a list of ids or an id :param values: a dictionary with field names as key and written values as value :return: True or False """ model_data_obj = Pool().get('ir.model.data') # Allow root user to update/delete if Transaction().user == 0: return True if isinstance(ids, (int, long)): ids = [ids] with Transaction().set_user(0): model_data_ids = model_data_obj.search([ ('model', '=', self._name), ('db_id', 'in', ids), ]) if not model_data_ids: return True if values == None: return False for line in model_data_obj.browse(model_data_ids): if not line.values: continue xml_values = safe_eval(line.values, { 'Decimal': Decimal, 'datetime': datetime, }) for key, val in values.iteritems(): if key in xml_values and val != xml_values[key]: return False return True
def set_fields_add(self, ids, name, value): if isinstance(ids, list): ids = ids[0] if not value: return all_add_options = {} document = self.browse(ids) if document.add_options: all_add_options = safe_eval(document.add_options, { 'Decimal': Decimal, 'datetime': datetime }) if name == 'pole_order': all_add_options['pole_order'] = value elif name == 'pole_type': all_add_options['pole_type'] = value elif name == 'pole_maturity': all_add_options['pole_maturity'] = value elif name == 'pole_detail': all_add_options['pole_detail'] = value elif name == 'pole_code': all_add_options['pole_code'] = value elif name == 'pole_reserve': all_add_options['pole_reserve'] = value elif name == 'kind_payment_tax': all_add_options['kind_payment_tax'] = value elif name == 'status_payer_tax': all_add_options['status_payer_tax'] = value elif name == 'kbk_indicator': all_add_options['kbk_indicator'] = value elif name == 'okato_indicator': all_add_options['okato_indicator'] = value elif name == 'payment_details_tax': all_add_options['payment_details_tax'] = value elif name == 'number_doc_base_tax': all_add_options['number_doc_base_tax'] = value elif name == 'tax_period': all_add_options['tax_period'] = value self.write(ids, {'add_options': str(all_add_options)})
def set_fields_add(self, ids, name, value): if isinstance(ids, list): ids = ids[0] if not value: return all_add_options = {} document = self.browse(ids) if document.add_options: all_add_options = safe_eval(document.add_options, { 'Decimal': Decimal, 'datetime': datetime}) if name == 'pole_order': all_add_options['pole_order'] = value elif name == 'pole_type': all_add_options['pole_type'] = value elif name == 'pole_maturity': all_add_options['pole_maturity'] = value elif name == 'pole_detail': all_add_options['pole_detail'] = value elif name == 'pole_code': all_add_options['pole_code'] = value elif name == 'pole_reserve': all_add_options['pole_reserve'] = value elif name == 'kind_payment_tax': all_add_options['kind_payment_tax'] = value elif name == 'status_payer_tax': all_add_options['status_payer_tax'] = value elif name == 'kbk_indicator': all_add_options['kbk_indicator'] = value elif name == 'okato_indicator': all_add_options['okato_indicator'] = value elif name == 'payment_details_tax': all_add_options['payment_details_tax'] = value elif name == 'number_doc_base_tax': all_add_options['number_doc_base_tax'] = value elif name == 'tax_period': all_add_options['tax_period'] = value self.write(ids, {'add_options': str(all_add_options)})
def get_path(cls, attachments, name): pool = Pool() Collection = pool.get('webdav.collection') paths = dict((a.id, None) for a in attachments) resources = {} resource2attachments = {} for attachment in attachments: if not attachment.resource: paths[attachment.id] = None continue model_name = attachment.resource.__name__ record_id = attachment.resource.id resources.setdefault(model_name, set()).add(record_id) resource2attachments.setdefault((model_name, record_id), []).append(attachment) collections = Collection.search([ ('model.model', 'in', resources.keys()), ]) for collection in collections: model_name = collection.model.model Model = pool.get(model_name) ids = list(resources[model_name]) domain = safe_eval(collection.domain or '[]') domain = [domain, ('id', 'in', ids)] records = Model.search(domain) for record in records: for attachment in resource2attachments[ (model_name, record.id)]: paths[attachment.id] = '/'.join((collection.rec_name, record.rec_name + '-' + str(record.id), attachment.name)) if 'webdav.collection' in resources: collection_ids = list(resources['webdav.collection']) for collection in Collection.browse(collection_ids): for attachment in resource2attachments[ ('webdav.collection', collection.id)]: paths[attachment.id] = '/'.join((collection.rec_name, attachment.name)) return paths
def get_path(self, ids, name): pool = Pool() collection_obj = pool.get('webdav.collection') paths = dict((x, None) for x in ids) attachments = self.browse(ids) resources = {} resource2attachments = {} for attachment in attachments: if not attachment.resource: paths[attachment.id] = None model_name, record_id = attachment.resource.split(',') record_id = int(record_id) resources.setdefault(model_name, set()).add(record_id) resource2attachments.setdefault((model_name, record_id), []).append(attachment) collection_ids = collection_obj.search([ ('model.model', 'in', resources.keys()), ]) for collection in collection_obj.browse(collection_ids): model_name = collection.model.model model_obj = pool.get(model_name) ids = list(resources[model_name]) domain = safe_eval(collection.domain or '[]') domain = [domain, ('id', 'in', ids)] record_ids = model_obj.search(domain) for record in model_obj.browse(record_ids): for attachment in resource2attachments[ (model_name, record.id)]: paths[attachment.id] = '/'.join((collection.rec_name, record.rec_name + '-' + str(record.id), attachment.name)) if 'webdav.collection' in resources: collection_ids = list(resources['webdav.collection']) for collection in collection_obj.browse(collection_ids): for attachment in resource2attachments[ ('webdav.collection', collection.id)]: paths[attachment.id] = '/'.join((collection.rec_name, attachment.name)) return paths
def __view_look_dom(cls, element, type, fields_width=None, fields_attrs=None): pool = Pool() Translation = pool.get('ir.translation') ModelData = pool.get('ir.model.data') Button = pool.get('ir.model.button') User = pool.get('res.user') if fields_width is None: fields_width = {} if not fields_attrs: fields_attrs = {} else: fields_attrs = copy.deepcopy(fields_attrs) childs = True if element.tag in ('field', 'label', 'separator', 'group', 'suffix', 'prefix'): for attr in ('name', 'icon', 'geometry'): if element.get(attr): fields_attrs.setdefault(element.get(attr), {}) try: field = cls._fields[element.get(attr)] if hasattr(field, 'model_name'): relation = field.model_name else: relation = field.get_target().__name__ except Exception: relation = False if relation and element.tag == 'field': childs = False views = {} mode = (element.attrib.pop('mode', None) or 'tree,form').split(',') view_ids = [] if element.get('view_ids'): for view_id in element.get('view_ids').split(','): try: view_ids.append(int(view_id)) except ValueError: view_ids.append(ModelData.get_id( *view_id.split('.'))) Relation = pool.get(relation) if (not len(element) and type == 'form' and field._type in ('one2many', 'many2many')): # Prefetch only the first view to prevent infinite # loop if view_ids: for view_id in view_ids: view = Relation.fields_view_get( view_id=view_id) views[str(view_id)] = view break else: for view_type in mode: views[view_type] = \ Relation.fields_view_get( view_type=view_type) break element.attrib['mode'] = ','.join(mode) element.attrib['view_ids'] = ','.join( map(str, view_ids)) fields_attrs[element.get(attr)].setdefault('views', {} ).update(views) if element.get('name') in fields_width: element.set('width', str(fields_width[element.get('name')])) # convert attributes into pyson encoder = PYSONEncoder() for attr in ('states', 'domain', 'spell', 'colors'): if element.get(attr): element.set(attr, encoder.encode(safe_eval(element.get(attr), CONTEXT))) if element.tag == 'button': button_name = element.attrib['name'] if button_name in cls._buttons: states = cls._buttons[button_name] else: states = {} groups = set(User.get_groups()) button_groups = Button.get_groups(cls.__name__, button_name) if button_groups and not groups & button_groups: states = states.copy() states['readonly'] = True element.set('states', encoder.encode(states)) # translate view if Transaction().language != 'en_US': for attr in ('string', 'sum', 'confirm', 'help'): if element.get(attr): trans = Translation.get_source(cls.__name__, 'view', Transaction().language, element.get(attr)) if trans: element.set(attr, trans) # Set header string if element.tag in ('form', 'tree', 'graph'): element.set('string', cls.view_header_get( element.get('string') or '', view_type=element.tag)) if element.tag == 'tree' and element.get('sequence'): fields_attrs.setdefault(element.get('sequence'), {}) if childs: for field in element: fields_attrs = cls.__view_look_dom(field, type, fields_width=fields_width, fields_attrs=fields_attrs) return fields_attrs
def fields_view_get(cls, view_id=None, view_type='form'): ''' Return a view definition. If view_id is None the first one will be used of view_type. The definition is a dictionary with keys: - model: the model name - arch: the xml description of the view - fields: a dictionary with the definition of each field in the view ''' key = (cls.__name__, view_id, view_type) result = cls._fields_view_get_cache.get(key) if result: return result result = {'model': cls.__name__} pool = Pool() View = pool.get('ir.ui.view') test = True model = True view = None inherit_view_id = False while test: if view_id: domain = [('id', '=', view_id)] if model: domain.append(('model', '=', cls.__name__)) views = View.search(domain, order=[]) else: domain = [ ('model', '=', cls.__name__), ('type', '=', view_type), ] order = [ ('inherit', 'DESC'), ('priority', 'ASC'), ('id', 'ASC'), ] views = View.search(domain, order=order) if not views: break view = views[0] test = view.inherit if test: inherit_view_id = view.id view_id = test.id if test else view.id model = False # if a view was found if view: result['type'] = view.type result['view_id'] = view_id result['arch'] = view.arch result['field_childs'] = view.field_childs # Check if view is not from an inherited model if view.model != cls.__name__: Inherit = pool.get(view.model) result['arch'] = Inherit.fields_view_get( result['view_id'])['arch'] view_id = inherit_view_id # get all views which inherit from (ie modify) this view views = View.search([ 'OR', [ ('inherit', '=', view_id), ('model', '=', cls.__name__), ], [ ('id', '=', view_id), ('inherit', '!=', None), ], ], order=[ ('priority', 'ASC'), ('id', 'ASC'), ]) raise_p = False while True: try: views.sort(key=lambda x: cls._modules_list.index(x.module or None)) break except ValueError: if raise_p: raise # There is perhaps a new module in the directory ModelView._reset_modules_list() raise_p = True for view in views: if view.domain: if not safe_eval(view.domain, {'context': Transaction().context}): continue if not view.arch or not view.arch.strip(): continue result['arch'] = _inherit_apply(result['arch'], view.arch) # otherwise, build some kind of default view else: if view_type == 'form': res = cls.fields_get() xml = '''<?xml version="1.0"?>''' \ '''<form string="%s" col="4">''' % (cls.__doc__,) for i in res: if i in ('create_uid', 'create_date', 'write_uid', 'write_date', 'id', 'rec_name'): continue if res[i]['type'] not in ('one2many', 'many2many'): xml += '<label name="%s"/>' % (i,) xml += '<field name="%s"/>' % (i,) if res[i]['type'] == 'text': xml += "<newline/>" else: xml += '<field name="%s" colspan="4"/>' % (i,) xml += "</form>" elif view_type == 'tree': field = 'id' if cls._rec_name in cls._fields: field = cls._rec_name xml = '''<?xml version="1.0"?>''' \ '''<tree string="%s"><field name="%s"/></tree>''' \ % (cls.__doc__, field) else: xml = '' result['type'] = view_type result['arch'] = xml result['field_childs'] = False result['view_id'] = 0 # Update arch and compute fields from arch parser = etree.XMLParser(remove_blank_text=True) tree = etree.fromstring(result['arch'], parser) xarch, xfields = cls._view_look_dom_arch(tree, result['type'], result['field_childs']) result['arch'] = xarch result['fields'] = xfields cls._fields_view_get_cache.set(key, result) return result
def startElement(self, name, attributes): cursor = Transaction().cursor values = {} self.xml_id = attributes['id'] for attr in ('name', 'icon', 'sequence', 'parent', 'action', 'groups'): if attributes.get(attr): values[attr] = attributes.get(attr) if attributes.get('active'): values['active'] = bool(safe_eval(attributes['active'])) if values.get('parent'): values['parent'] = self.mh.get_id(values['parent']) action_name = None if values.get('action'): action_id = self.mh.get_id(values['action']) # TODO maybe use a prefetch for this: cursor.execute(cursor.limit_clause( "SELECT a.name, a.type, v.type, v.field_childs, icon.name " \ "FROM ir_action a " \ "LEFT JOIN ir_action_report report ON (a.id = report.action) "\ "LEFT JOIN ir_action_act_window act ON (a.id = act.action) " \ "LEFT JOIN ir_action_wizard wizard ON (a.id = wizard.action) "\ "LEFT JOIN ir_action_url url ON (a.id = url.action) " \ "LEFT JOIN ir_action_act_window_view wv ON " \ "(act.id = wv.act_window) " \ "LEFT JOIN ir_ui_view v ON (v.id = wv.view) " \ "LEFT JOIN ir_ui_icon icon ON (a.icon = icon.id) " \ "WHERE report.id = %s " \ "OR act.id = %s " \ "OR wizard.id = %s " \ "OR url.id = %s " \ "ORDER by wv.sequence", 1), (action_id, action_id, action_id, action_id)) action_name, action_type, view_type, field_childs, icon_name = \ cursor.fetchone() values['action'] = '%s,%s' % (action_type, action_id) icon = attributes.get('icon', '') if icon: values['icon'] = icon elif icon_name: values['icon'] = icon_name elif action_type == 'ir.action.wizard': values['icon'] = 'tryton-executable' elif action_type == 'ir.action.report': values['icon'] = 'tryton-print' elif action_type == 'ir.action.act_window': if view_type == 'tree': if field_childs: values['icon'] = 'tryton-tree' else: values['icon'] = 'tryton-list' elif view_type == 'form': values['icon'] = 'tryton-new' elif view_type == 'graph': values['icon'] = 'tryton-graph' elif view_type == 'calendar': values['icon'] = 'tryton-calendar' elif action_type == 'ir.action.url': values['icon'] = 'tryton-web-browser' else: values['icon'] = 'tryton-new' if values.get('groups'): raise Exception("Please use separate records for groups") if not values.get('name'): if not action_name: raise Exception("Please provide at least a 'name' attributes " "or a 'action' attributes on the menuitem tags.") else: values['name'] = action_name self.values = values
def __view_look_dom(self, element, type, fields_width=None): pool = Pool() translation_obj = pool.get("ir.translation") model_data_obj = pool.get("ir.model.data") button_obj = pool.get("ir.model.button") user_obj = pool.get("res.user") if fields_width is None: fields_width = {} fields_attrs = {} childs = True if element.tag in ("field", "label", "separator", "group"): for attr in ("name", "icon"): if element.get(attr): attrs = {} try: if element.get(attr) in self._columns: field = self._columns[element.get(attr)] else: field = self._inherit_fields[element.get(attr)][2] if hasattr(field, "model_name"): relation = field.model_name else: relation = field.get_target()._name except Exception: relation = False if relation and element.tag == "field": childs = False views = {} mode = (element.attrib.pop("mode", None) or "tree,form").split(",") view_ids = [] if element.get("view_ids"): for view_id in element.get("view_ids").split(","): try: view_ids.append(int(view_id)) except ValueError: view_ids.append(model_data_obj.get_id(*view_id.split("."))) relation_obj = pool.get(relation) if not len(element) and type == "form" and field._type in ("one2many", "many2many"): # Prefetch only the first view to prevent infinite # loop if view_ids: for view_id in view_ids: view = relation_obj.fields_view_get(view_id=view_id) views[view["type"]] = view break else: for view_type in mode: views[view_type] = relation_obj.fields_view_get(view_type=view_type) break element.attrib["mode"] = ",".join(mode) element.attrib["view_ids"] = ",".join(map(str, view_ids)) attrs = {"views": views} fields_attrs[element.get(attr)] = attrs if element.get("name") in fields_width: element.set("width", str(fields_width[element.get("name")])) # convert attributes into pyson encoder = PYSONEncoder() for attr in ("states", "domain", "context", "digits", "add_remove", "spell", "colors"): if element.get(attr): element.set(attr, encoder.encode(safe_eval(element.get(attr), CONTEXT))) if element.tag == "button": if element.get("type", "object") == "object": assert not element.get("states") button_name = element.attrib["name"] if button_name in self._buttons: states = self._buttons[button_name] else: states = {} groups = set(user_obj.get_groups()) button_groups = button_obj.get_groups(self._name, button_name) if button_groups and not groups & button_groups: states = states.copy() states["readonly"] = True element.set("states", encoder.encode(states)) # translate view if Transaction().language != "en_US": for attr in ("string", "sum", "confirm", "help"): if element.get(attr): trans = translation_obj.get_source(self._name, "view", Transaction().language, element.get(attr)) if trans: element.set(attr, trans) # Set header string if element.tag in ("form", "tree", "graph"): element.set("string", self.view_header_get(element.get("string") or "", view_type=element.tag)) if element.tag == "tree" and element.get("sequence"): fields_attrs.setdefault(element.get("sequence"), {}) if childs: for field in element: fields_attrs.update(self.__view_look_dom(field, type, fields_width=fields_width)) return fields_attrs
def fields_view_get(self, view_id=None, view_type="form", hexmd5=None): """ Return a view definition. :param view_id: the id of the view, if None the first one will be used :param view_type: the type of the view if view_id is None :param hexmd5: if filled, the function will return True if the result has the same md5 :return: a dictionary with keys: - model: the model name - arch: the xml description of the view - fields: a dictionary with the definition of each field in the view - md5: the check sum of the dictionary without this checksum """ result = {"model": self._name} pool = Pool() test = True model = True sql_res = False inherit_view_id = False cursor = Transaction().cursor while test: if view_id: where = (model and (" and model='%s'" % (self._name,))) or "" cursor.execute( "SELECT arch, field_childs, id, type, " "inherit, model " "FROM ir_ui_view WHERE id = %s " + where, (view_id,), ) else: cursor.execute( "SELECT arch, field_childs, id, type, " "inherit, model " "FROM ir_ui_view " "WHERE model = %s AND type = %s " "ORDER BY inherit DESC, priority ASC, id ASC", (self._name, view_type), ) sql_res = cursor.fetchone() if not sql_res: break test = sql_res[4] if test: inherit_view_id = sql_res[2] view_id = test or sql_res[2] model = False # if a view was found if sql_res: result["type"] = sql_res[3] result["view_id"] = view_id result["arch"] = sql_res[0] result["field_childs"] = sql_res[1] or False # Check if view is not from an inherited model if sql_res[5] != self._name: inherit_obj = pool.get(sql_res[5]) result["arch"] = inherit_obj.fields_view_get(result["view_id"])["arch"] view_id = inherit_view_id # get all views which inherit from (ie modify) this view cursor.execute( "SELECT arch, domain, module FROM ir_ui_view " "WHERE (inherit = %s AND model = %s) OR " " (id = %s AND inherit IS NOT NULL) " "ORDER BY priority ASC, id ASC", (view_id, self._name, view_id), ) sql_inherit = cursor.fetchall() raise_p = False while True: try: sql_inherit.sort(key=lambda x: self._modules_list.index(x[2] or None)) break except ValueError: if raise_p: raise # There is perhaps a new module in the directory ModelView._reset_modules_list() raise_p = True for arch, domain, _ in sql_inherit: if domain: if not safe_eval(domain, {"context": Transaction().context}): continue if not arch or not arch.strip(): continue result["arch"] = _inherit_apply(result["arch"], arch) # otherwise, build some kind of default view else: if view_type == "form": res = self.fields_get() xml = """<?xml version="1.0" encoding="utf-8"?>""" """<form string="%s">""" % (self._description,) for i in res: if i in ("create_uid", "create_date", "write_uid", "write_date", "id", "rec_name"): continue if res[i]["type"] not in ("one2many", "many2many"): xml += '<label name="%s"/>' % (i,) xml += '<field name="%s"/>' % (i,) if res[i]["type"] == "text": xml += "<newline/>" xml += "</form>" elif view_type == "tree": field = "id" if self._rec_name in self._columns: field = self._rec_name xml = """<?xml version="1.0" encoding="utf-8"?>""" """<tree string="%s"><field name="%s"/></tree>""" % ( self._description, field, ) else: xml = "" result["type"] = view_type result["arch"] = xml result["field_childs"] = False result["view_id"] = 0 # Update arch and compute fields from arch parser = etree.XMLParser(remove_blank_text=True) tree = etree.fromstring(result["arch"], parser) xarch, xfields = self._view_look_dom_arch(tree, result["type"], result["field_childs"]) result["arch"] = xarch result["fields"] = xfields # Compute md5 if hashlib: result["md5"] = hashlib.md5(str(result)).hexdigest() else: result["md5"] = md5.new(str(result)).hexdigest() if hexmd5 == result["md5"]: return True return result
def __view_look_dom(cls, element, type, fields_width=None, fields_attrs=None): pool = Pool() Translation = pool.get("ir.translation") ModelData = pool.get("ir.model.data") Button = pool.get("ir.model.button") User = pool.get("res.user") if fields_width is None: fields_width = {} if not fields_attrs: fields_attrs = {} else: fields_attrs = copy.deepcopy(fields_attrs) childs = True if element.tag in ("field", "label", "separator", "group", "suffix", "prefix"): for attr in ("name", "icon"): if element.get(attr): fields_attrs.setdefault(element.get(attr), {}) try: field = cls._fields[element.get(attr)] if hasattr(field, "model_name"): relation = field.model_name else: relation = field.get_target().__name__ except Exception: relation = False if relation and element.tag == "field": childs = False views = {} mode = (element.attrib.pop("mode", None) or "tree,form").split(",") view_ids = [] if element.get("view_ids"): for view_id in element.get("view_ids").split(","): try: view_ids.append(int(view_id)) except ValueError: view_ids.append(ModelData.get_id(*view_id.split("."))) Relation = pool.get(relation) if not len(element) and type == "form" and field._type in ("one2many", "many2many"): # Prefetch only the first view to prevent infinite # loop if view_ids: for view_id in view_ids: view = Relation.fields_view_get(view_id=view_id) views[str(view_id)] = view break else: for view_type in mode: views[view_type] = Relation.fields_view_get(view_type=view_type) break element.attrib["mode"] = ",".join(mode) element.attrib["view_ids"] = ",".join(map(str, view_ids)) fields_attrs[element.get(attr)].setdefault("views", {}).update(views) if element.get("name") in fields_width: element.set("width", str(fields_width[element.get("name")])) # convert attributes into pyson encoder = PYSONEncoder() for attr in ("states", "domain", "context", "digits", "add_remove", "spell", "colors"): if element.get(attr): element.set(attr, encoder.encode(safe_eval(element.get(attr), CONTEXT))) if element.tag == "button": button_name = element.attrib["name"] if button_name in cls._buttons: states = cls._buttons[button_name] else: states = {} groups = set(User.get_groups()) button_groups = Button.get_groups(cls.__name__, button_name) if button_groups and not groups & button_groups: states = states.copy() states["readonly"] = True element.set("states", encoder.encode(states)) # translate view if Transaction().language != "en_US": for attr in ("string", "sum", "confirm", "help"): if element.get(attr): trans = Translation.get_source(cls.__name__, "view", Transaction().language, element.get(attr)) if trans: element.set(attr, trans) # Set header string if element.tag in ("form", "tree", "graph"): element.set("string", cls.view_header_get(element.get("string") or "", view_type=element.tag)) if element.tag == "tree" and element.get("sequence"): fields_attrs.setdefault(element.get("sequence"), {}) if childs: for field in element: fields_attrs = cls.__view_look_dom(field, type, fields_width=fields_width, fields_attrs=fields_attrs) return fields_attrs
def get_childs(self, uri, filter=None, cache=None): pool = Pool() report_obj = pool.get('ir.action.report') res = [] if filter: return [] if not uri: collection_ids = self.search([ ('parent', '=', None), ]) for collection in self.browse(collection_ids): if '/' in collection.name: continue res.append(collection.name) if cache is not None: cache.setdefault(self._name, {}) cache[self._name][collection.id] = {} return res object_name, object_id = self._uri2object(uri, cache=cache) if object_name == self._name and object_id: collection = self.browse(object_id) if collection.model: model_obj = pool.get(collection.model.model) if not model_obj: return res model_ids = model_obj.search( safe_eval(collection.domain or "[]")) for child in model_obj.browse(model_ids): if '/' in child.rec_name: continue res.append(child.rec_name + '-' + str(child.id)) if cache is not None: cache.setdefault(model_obj._name, {}) cache[model_obj._name][child.id] = {} return res else: for child in collection.childs: if '/' in child.name: continue res.append(child.name) if cache is not None: cache.setdefault(self._name, {}) cache[self._name][child.id] = {} if object_name not in ('ir.attachment', 'ir.action.report'): report_ids = report_obj.search([ ('model', '=', object_name), ]) reports = report_obj.browse(report_ids) for report in reports: report_name = report.name + '-' + str(report.id) \ + '.' + report.extension if '/' in report_name: continue res.append(report_name) if cache is not None: cache.setdefault(report_obj._name, {}) cache[report_obj._name][report.id] = {} attachment_obj = pool.get('ir.attachment') attachment_ids = attachment_obj.search([ ('resource', '=', '%s,%s' % (object_name, object_id)), ]) for attachment in attachment_obj.browse(attachment_ids): if attachment.name and not attachment.link: if '/' in attachment.name: continue res.append(attachment.name) if cache is not None: cache.setdefault(attachment_obj._name, {}) cache[attachment_obj._name][attachment.id] = {} return res
def import_record(self, model, values, fs_id): module = self.module if not fs_id: raise Exception('import_record : Argument fs_id is mandatory') if '.' in fs_id: assert len(fs_id.split('.')) == 2, '"%s" contains too many dots. '\ 'file system ids should contain ot most one dot ! ' \ 'These are used to refer to other modules data, ' \ 'as in module.reference_id' % (fs_id) module, fs_id = fs_id.split('.') if not self.fs2db.get(module, fs_id): raise Exception('Reference to %s.%s not found' % \ (module, fs_id)) object_ref = self.pool.get(model) if self.fs2db.get(module, fs_id): # Remove this record from the to_delete list. This means that # the corresponding record have been found. if module == self.module and fs_id in self.to_delete: self.to_delete.remove(fs_id) if self.noupdate: return # this record is already in the db: # XXX maybe use only one call to get() db_id, db_model, mdata_id, old_values = \ [self.fs2db.get(module, fs_id)[x] for x in \ ["db_id", "model", "id", "values"]] inherit_db_ids = {} inherit_mdata_ids = [] if not old_values: old_values = {} else: old_values = safe_eval(old_values, { 'Decimal': Decimal, 'datetime': datetime, }) for key in old_values: if isinstance(old_values[key], str): # Fix for migration to unicode old_values[key] = old_values[key].decode('utf-8') if model != db_model: raise Exception("This record try to overwrite " \ "data with the wrong model: %s (module: %s)" % (fs_id, module)) #Re-create record if it was deleted if not self.fs2db.get_browserecord( module, object_ref._name, db_id): with Transaction().set_context( module=module, language='en_US'): db_id = object_ref.create(values) # reset_browsercord self.fs2db.reset_browsercord(module, object_ref._name, db_id) record = self.fs2db.get_browserecord(module, object_ref._name, db_id) for table, field_name, field in \ object_ref._inherit_fields.values(): inherit_db_ids[table] = record[field_name].id for table in inherit_db_ids.keys(): data_id = self.modeldata_obj.search([ ('fs_id', '=', fs_id), ('module', '=', module), ('model', '=', table), ], limit=1) if data_id: self.modeldata_obj.write(data_id, { 'db_id': inherit_db_ids[table], 'inherit': True, }) else: data_id = self.modeldata_obj.create({ 'fs_id': fs_id, 'module': module, 'model': table, 'db_id': inherit_db_ids[table], 'inherit': True, }) inherit_mdata_ids.append((table, data_id)) data_id = self.modeldata_obj.search([ ('fs_id', '=', fs_id), ('module', '=', module), ('model', '=', object_ref._name), ], limit=1)[0] self.modeldata_obj.write(data_id, { 'db_id': db_id, }) self.fs2db.get(module, fs_id)["db_id"] = db_id db_val = self.fs2db.get_browserecord(module, object_ref._name, db_id) if not db_val: db_val = object_ref.browse(db_id) to_update = {} for key in values: db_field = self._clean_value(key, db_val, object_ref) # if the fs value is the same has in the db, whe ignore it val = values[key] if isinstance(values[key], str): # Fix for migration to unicode val = values[key].decode('utf-8') if db_field == val: continue # we cannot update a field if it was changed by a user... if key not in old_values: if key in object_ref._columns: expected_value = object_ref._defaults.get( key, lambda *a: None)() else: inherit_obj = self.pool.get( object_ref._inherit_fields[key][0]) expected_value = inherit_obj._defaults.get( key, lambda *a: None)() else: expected_value = old_values[key] # Migration from 2.0: Reference field change value if key in object_ref._columns: field_type = object_ref._columns[key]._type else: field_type = object_ref._inherit_fields[key][2]._type if field_type == 'reference': if (expected_value and expected_value.endswith(',0') and not db_field): db_field = expected_value # ... and we consider that there is an update if the # expected value differs from the actual value, _and_ # if they are not false in a boolean context (ie None, # False, {} or []) if db_field != expected_value and (db_field or expected_value): logging.getLogger("convert").warning( "Field %s of %s@%s not updated (id: %s), because "\ "it has changed since the last update" % \ (key, db_id, model, fs_id)) continue # so, the field in the fs and in the db are different, # and no user changed the value in the db: to_update[key] = values[key] # if there is values to update: if to_update: # write the values in the db: with Transaction().set_context( module=module, language='en_US'): object_ref.write(db_id, to_update) self.fs2db.reset_browsercord(module, object_ref._name, db_id) if not inherit_db_ids: record = object_ref.browse(db_id) for table, field_name, field in \ object_ref._inherit_fields.values(): inherit_db_ids[table] = record[field_name].id if not inherit_mdata_ids: for table in inherit_db_ids.keys(): data_id = self.modeldata_obj.search([ ('fs_id', '=', fs_id), ('module', '=', module), ('model', '=', table), ], limit=1) inherit_mdata_ids.append((table, data_id)) if to_update: # re-read it: this ensure that we store the real value # in the model_data table: db_val = self.fs2db.get_browserecord(module, object_ref._name, db_id) if not db_val: db_val = object_ref.browse(db_id) for key in to_update: values[key] = self._clean_value(key, db_val, object_ref) if module != self.module: temp_values = old_values.copy() temp_values.update(values) values = temp_values if values != old_values: self.modeldata_obj.write(mdata_id, { 'fs_id': fs_id, 'model': model, 'module': module, 'db_id': db_id, 'values': str(values), 'date_update': datetime.datetime.now(), }) for table, inherit_mdata_id in inherit_mdata_ids: self.modeldata_obj.write(inherit_mdata_id, { 'fs_id': fs_id, 'model': table, 'module': module, 'db_id': inherit_db_ids[table], 'values': str(values), 'date_update': datetime.datetime.now(), }) # reset_browsercord to keep cache memory low self.fs2db.reset_browsercord(module, object_ref._name, db_id) else: # this record is new, create it in the db: with Transaction().set_context(module=module, language='en_US'): db_id = object_ref.create(values) inherit_db_ids = {} record = object_ref.browse(db_id) for table, field_name, field in ( object_ref._inherit_fields.values()): inherit_db_ids[table] = record[field_name].id # re-read it: this ensure that we store the real value # in the model_data table: db_val = object_ref.browse(db_id) for key in values: values[key] = self._clean_value(key, db_val, object_ref) for table in inherit_db_ids.keys(): self.modeldata_obj.create({ 'fs_id': fs_id, 'model': table, 'module': module, 'db_id': inherit_db_ids[table], 'values': str(values), 'inherit': True, 'noupdate': self.noupdate, }) mdata_id = self.modeldata_obj.create({ 'fs_id': fs_id, 'model': model, 'module': module, 'db_id': db_id, 'values': str(values), 'noupdate': self.noupdate, }) # update fs2db: self.fs2db.set(module, fs_id, { "db_id": db_id, "model": model, "id": mdata_id, "values": str(values)}) self.fs2db.reset_browsercord(module, model, db_id)
) JSONDecoder.register( 'time', lambda dct: datetime.time( dct['hour'], dct['minute'], dct['second'], dct['microsecond'] ) ) JSONDecoder.register( 'buffer', lambda dct: buffer(base64.decodestring(dct['base64'])) ) JSONDecoder.register( 'Decimal', lambda dct: Decimal(dct['decimal']) ) JSONDecoder.register( 'Model', lambda dct: safe_eval(dct['repr'], {'Pool': Pool}) ) class JSONEncoder(json.JSONEncoder): serializers = {} def __init__(self, *args, **kwargs): super(JSONEncoder, self).__init__(*args, **kwargs) # Force to use our custom decimal with simplejson self.use_decimal = False @classmethod def register(cls, klass, encoder): assert klass not in cls.serializers
return dct JSONDecoder.register( 'datetime', lambda dct: datetime.datetime(dct['year'], dct['month'], dct[ 'day'], dct['hour'], dct['minute'], dct['second'], dct['microsecond'])) JSONDecoder.register( 'date', lambda dct: datetime.date(dct['year'], dct['month'], dct['day'])) JSONDecoder.register( 'time', lambda dct: datetime.time(dct['hour'], dct['minute'], dct[ 'second'], dct['microsecond'])) JSONDecoder.register('buffer', lambda dct: buffer(base64.decodestring(dct['base64']))) JSONDecoder.register('Decimal', lambda dct: Decimal(dct['decimal'])) JSONDecoder.register('Model', lambda dct: safe_eval(dct['repr'], {'Pool': Pool})) class JSONEncoder(json.JSONEncoder): serializers = {} def __init__(self, *args, **kwargs): super(JSONEncoder, self).__init__(*args, **kwargs) # Force to use our custom decimal with simplejson self.use_decimal = False @classmethod def register(cls, klass, encoder): assert klass not in cls.serializers cls.serializers[klass] = encoder
def fields_view_get(cls, view_id=None, view_type="form"): """ Return a view definition. If view_id is None the first one will be used of view_type. The definition is a dictionary with keys: - model: the model name - arch: the xml description of the view - fields: a dictionary with the definition of each field in the view """ key = (cls.__name__, view_id, view_type) result = cls._fields_view_get_cache.get(key) if result: return result result = {"model": cls.__name__} pool = Pool() View = pool.get("ir.ui.view") test = True model = True view = None inherit_view_id = False while test: if view_id: domain = [("id", "=", view_id)] if model: domain.append(("model", "=", cls.__name__)) views = View.search(domain, order=[]) else: domain = [("model", "=", cls.__name__), ("type", "=", view_type)] order = [("inherit", "DESC"), ("priority", "ASC"), ("id", "ASC")] views = View.search(domain, order=order) if not views: break view = views[0] test = view.inherit if test: inherit_view_id = view.id view_id = test.id if test else view.id model = False # if a view was found if view: result["type"] = view.type result["view_id"] = view_id result["arch"] = view.arch result["field_childs"] = view.field_childs # Check if view is not from an inherited model if view.model != cls.__name__: Inherit = pool.get(view.model) result["arch"] = Inherit.fields_view_get(result["view_id"])["arch"] view_id = inherit_view_id # get all views which inherit from (ie modify) this view views = View.search( [ "OR", [("inherit", "=", view_id), ("model", "=", cls.__name__)], [("id", "=", view_id), ("inherit", "!=", None)], ], order=[("priority", "ASC"), ("id", "ASC")], ) raise_p = False while True: try: views.sort(key=lambda x: cls._modules_list.index(x.module or None)) break except ValueError: if raise_p: raise # There is perhaps a new module in the directory ModelView._reset_modules_list() raise_p = True for view in views: if view.domain: if not safe_eval(view.domain, {"context": Transaction().context}): continue if not view.arch or not view.arch.strip(): continue result["arch"] = _inherit_apply(result["arch"], view.arch) # otherwise, build some kind of default view else: if view_type == "form": res = cls.fields_get() xml = """<?xml version="1.0"?>""" """<form string="%s" col="4">""" % (cls.__doc__,) for i in res: if i in ("create_uid", "create_date", "write_uid", "write_date", "id", "rec_name"): continue if res[i]["type"] not in ("one2many", "many2many"): xml += '<label name="%s"/>' % (i,) xml += '<field name="%s"/>' % (i,) if res[i]["type"] == "text": xml += "<newline/>" else: xml += '<field name="%s" colspan="4"/>' % (i,) xml += "</form>" elif view_type == "tree": field = "id" if cls._rec_name in cls._fields: field = cls._rec_name xml = """<?xml version="1.0"?>""" """<tree string="%s"><field name="%s"/></tree>""" % ( cls.__doc__, field, ) else: xml = "" result["type"] = view_type result["arch"] = xml result["field_childs"] = False result["view_id"] = 0 # Update arch and compute fields from arch parser = etree.XMLParser(remove_blank_text=True) tree = etree.fromstring(result["arch"], parser) xarch, xfields = cls._view_look_dom_arch(tree, result["type"], result["field_childs"]) result["arch"] = xarch result["fields"] = xfields cls._fields_view_get_cache.set(key, result) return result
def get_childs(cls, uri, filter=None, cache=None): pool = Pool() Report = pool.get('ir.action.report') res = [] if filter: return [] if not uri: collections = cls.search([ ('parent', '=', None), ]) for collection in collections: if '/' in collection.name: continue res.append(collection.name) if cache is not None: cache.setdefault(cls.__name__, {}) cache[cls.__name__][collection.id] = {} return res object_name, object_id = cls._uri2object(uri, cache=cache) if object_name == cls.__name__ and object_id: collection = cls(object_id) if collection.model: Model = pool.get(collection.model.model) if not Model: return res models = Model.search( safe_eval(collection.domain or "[]")) for child in models: if '/' in child.rec_name: continue res.append(child.rec_name + '-' + str(child.id)) if cache is not None: cache.setdefault(Model.__name__, {}) cache[Model.__name__][child.id] = {} return res else: for child in collection.childs: if '/' in child.name: continue res.append(child.name) if cache is not None: cache.setdefault(cls.__name__, {}) cache[cls.__name__][child.id] = {} if object_name not in ('ir.attachment', 'ir.action.report'): reports = Report.search([ ('model', '=', object_name), ]) for report in reports: report_name = (report.name + '-' + str(report.id) + '.' + report.extension) if '/' in report_name: continue res.append(report_name) if cache is not None: cache.setdefault(Report.__name__, {}) cache[Report.__name__][report.id] = {} Attachment = pool.get('ir.attachment') attachments = Attachment.search([ ('resource', '=', '%s,%s' % (object_name, object_id)), ]) for attachment in attachments: if attachment.name and not attachment.link: if '/' in attachment.name: continue res.append(attachment.name) if cache is not None: cache.setdefault(Attachment.__name__, {}) cache[Attachment.__name__][attachment.id] = {} return res
def get_fields(self, ids, names): if not ids: return {} res = {} for line in self.browse(ids): all_add_options = False if line.add_options: all_add_options = safe_eval(line.add_options, { 'Decimal': Decimal, 'datetime': datetime }) for name in names: res.setdefault(name, {}) res[name].setdefault(line.id, False) if name == 'number_doc': if name == 'number_doc': if line.type_transaction in ('expense', 'expense_tax'): res[name][line.id] = line.number_our else: res[name][line.id] = line.number_in elif name == 'state_doc': res[name][line.id] = line.state elif name == 'from_party_doc': res[name][line.id] = line.from_party.id elif name == 'to_party_doc': res[name][line.id] = line.to_party.id elif name == 'template_bank': res[name][line.id] = line.template.id elif name == 'content': res[name][line.id] = line.note elif all_add_options and name == 'pole_order': res[name][line.id] = all_add_options.get('pole_order') elif all_add_options and name == 'pole_type': res[name][line.id] = all_add_options.get('pole_type') elif all_add_options and name == 'pole_maturity': res[name][line.id] = all_add_options.get('pole_maturity') elif all_add_options and name == 'pole_detail': res[name][line.id] = all_add_options.get('pole_detail') elif all_add_options and name == 'pole_code': res[name][line.id] = all_add_options.get('pole_code') elif all_add_options and name == 'pole_reserve': res[name][line.id] = all_add_options.get('pole_reserve') elif all_add_options and name == 'kind_payment_tax': res[name][line.id] = all_add_options.get( 'kind_payment_tax') elif all_add_options and name == 'status_payer_tax': res[name][line.id] = all_add_options.get( 'status_payer_tax') elif all_add_options and name == 'kbk_indicator': res[name][line.id] = all_add_options.get('kbk_indicator') elif all_add_options and name == 'okato_indicator': res[name][line.id] = all_add_options.get('okato_indicator') elif all_add_options and name == 'payment_details_tax': res[name][line.id] = all_add_options.get( 'payment_details_tax') elif all_add_options and name == 'number_doc_base_tax': res[name][line.id] = all_add_options.get( 'number_doc_base_tax') elif all_add_options and name == 'tax_period': res[name][line.id] = all_add_options.get('tax_period') return res