def report_move_lines_action(self): domain = safe_eval(self.domain) if 'date_from' in self.env.context.get('context', {}): if self.env.context['context'].get('date_from'): domain = expression.AND([ domain, [('date', '>=', self.env.context['context']['date_from'])] ]) if self.env.context['context'].get('date_to'): domain = expression.AND([ domain, [('date', '<=', self.env.context['context']['date_to'])] ]) if self.env.context['context'].get('state', 'all') == 'posted': domain = expression.AND( [domain, [('move_id.state', '=', 'posted')]]) if self.env.context['context'].get('company_ids'): domain = expression.AND([ domain, [('company_id', 'in', self.env.context['context']['company_ids'])] ]) return { 'type': 'ir.actions.act_window', 'name': 'Journal Items (%s)' % self.name, 'res_model': 'account.move.line', 'view_mode': 'tree,form', 'domain': domain, }
def code_search(self, name, args=None, operator='ilike', limit=100): if not args: args = [] if name: category_names = name.split(' / ') parents = list(category_names) child = parents.pop() domain = [('name', operator, child)] if parents: names_ids = self.name_search(' / '.join(parents), args=args, operator='ilike', limit=limit) category_ids = [name_id[0] for name_id in names_ids] if operator in expression.NEGATIVE_TERM_OPERATORS: categories = self.search([('id', 'not in', category_ids)]) domain = expression.OR([[('parent_id', 'in', categories.ids)], domain]) else: domain = expression.AND([[('parent_id', 'in', category_ids) ], domain]) for i in range(1, len(category_names)): domain = [[('name', operator, ' / '.join(category_names[-1 - i:]))], domain] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = expression.AND(domain) else: domain = expression.OR(domain) categories = self.search(expression.AND([domain, args]), limit=limit) else: categories = self.search(args, limit=limit) return categories.name_get()
def _search_group(self, cr, uid, obj, name, args, context=None): operand = args[0][2] operator = args[0][1] lst = True if isinstance(operand, bool): domains = [[('name', operator, operand)], [('category_id.name', operator, operand)]] if operator in expression.NEGATIVE_TERM_OPERATORS == (not operand): return expression.AND(domains) else: return expression.OR(domains) if isinstance(operand, basestring): lst = False operand = [operand] where = [] for group in operand: values = filter(bool, group.split('/')) group_name = values.pop().strip() category_name = values and '/'.join(values).strip() or group_name group_domain = [('name', operator, lst and [group_name] or group_name)] category_domain = [('category_id.name', operator, lst and [category_name] or category_name)] if operator in expression.NEGATIVE_TERM_OPERATORS and not values: category_domain = expression.OR([category_domain, [('category_id', '=', False)]]) if (operator in expression.NEGATIVE_TERM_OPERATORS) == (not values): sub_where = expression.AND([group_domain, category_domain]) else: sub_where = expression.OR([group_domain, category_domain]) if operator in expression.NEGATIVE_TERM_OPERATORS: where = expression.AND([where, sub_where]) else: where = expression.OR([where, sub_where]) return where
def name_search(self, cr, uid, name, args=None, operator='ilike', context=None, limit=100): if not args: args = [] if not context: context = {} if name: # Be sure name_search is symetric to name_get categories = name.split('/') parents = list(categories) child = parents.pop() domain = [('name', operator, child)] if parents: names_ids = self.name_search( cr, uid, '/'.join(parents), args=args, operator='ilike', context=context, limit=limit) category_ids = [name_id[0] for name_id in names_ids] if operator in expression.NEGATIVE_TERM_OPERATORS: category_ids = self.search( cr, uid, [('id', 'not in', category_ids)]) domain = expression.OR( [[('parent_id', 'in', category_ids)], domain]) else: domain = expression.AND( [[('parent_id', 'in', category_ids)], domain]) for i in range(1, len(categories)): domain = [ [('name', operator, '/'.join(categories[-1 - i:]))], domain] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = expression.AND(domain) else: domain = expression.OR(domain) ids = self.search( cr, uid, expression.AND([domain, args]), limit=limit, context=context) else: ids = self.search(cr, uid, args, limit=limit, context=context) return self.name_get(cr, uid, ids, context)
def search(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False): """ Display only standalone contact matching ``args`` or having attached contact matching ``args`` """ if context is None: context = {} if context.get('search_show_all_positions') is False: args = expression.normalize_domain(args) attached_contact_args = expression.AND( (args, [('contact_type', '=', 'attached')])) attached_contact_ids = super(res_partner, self).search(cr, user, attached_contact_args, context=context) args = expression.OR(( expression.AND(([('contact_type', '=', 'standalone')], args)), [('other_contact_ids', 'in', attached_contact_ids)], )) return super(res_partner, self).search(cr, user, args, offset=offset, limit=limit, order=order, context=context, count=count)
def get_mention_suggestions(self, search, channel, exclude=None, limit=8): """ Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize partners registered to channel 'channel[channel_id]' if given, or partners that are followers of a document identified by 'channel[res_model]' and 'channel[res_id]' otherwise, then users, and finally extend the research to all partners. Exclude partners whose id is in 'exclude'. """ if exclude is None: exclude = [] members = [] users = [] partners = [] search_dom = expression.AND([ expression.OR([[('name', 'ilike', search)], [('email', 'ilike', search)]]), [('id', 'not in', exclude)] ]) fields = ['id', 'name', 'email'] def search_partners(domain, fields, limit, exclude): partners = self.search_read(domain, fields, limit=limit) limit -= len(partners) exclude += [partner['id'] for partner in partners] return partners, limit, exclude # Search users registered to the channel if 'channel_id' in channel: domain = expression.AND([[('channel_ids', 'in', [channel['channel_id']])], search_dom]) members, limit, exclude = search_partners(domain, fields, limit, exclude) else: domain = expression.AND([[('res_model', '=', channel['res_model']) ], [('res_id', '=', channel['res_id'])]]) followers = self.env['mail.followers'].search(domain) domain = expression.AND([[('id', 'in', followers.mapped('partner_id').ids)], search_dom]) members, limit, exclude = search_partners(domain, fields, limit, exclude) if limit > 0: # Search users domain = expression.AND([[('user_ids.id', '!=', False)], search_dom]) users, limit, exclude = search_partners(domain, fields, limit, exclude) if limit > 0: # Search partners partners = self.search_read(search_dom, fields, limit=limit) return [members, users, partners]
def _domain_get(self, cr, uid, ids, field_name, args, context=None): '''combine our domain with all domains to union/complement, this works recursively''' def eval_n(domain): '''parse a domain and normalize it''' try: domain = safe_eval(domain) except: domain = [expression.FALSE_LEAF] return expression.normalize_domain( domain or [expression.FALSE_LEAF]) result = {} for this in self.read( cr, uid, ids, ['domain_this', 'union_filter_ids', 'complement_filter_ids'], context=context): domain = eval_n(this['domain_this']) for u in self.read(cr, uid, this['union_filter_ids'], ['domain', 'evaluate_always', 'model_id'], context=context): if u['evaluate_always']: matching_ids = self.pool[u['model_id']].search( cr, uid, eval_n(u['domain']), context=context) domain = expression.OR([ domain, [('id', 'in', matching_ids)], ]) else: domain = expression.OR([domain, eval_n(u['domain'])]) for c in self.read(cr, uid, this['complement_filter_ids'], ['domain', 'evaluate_before_negate', 'model_id'], context=context): if c['evaluate_before_negate']: matching_ids = self.pool[c['model_id']].search( cr, uid, eval_n(c['domain']), context=context) domain = expression.AND([ domain, [('id', 'not in', matching_ids)], ]) else: domain = expression.AND([ domain, ['!'] + eval_n(c['domain'])]) result[this['id']] = str(expression.normalize_domain(domain)) return result
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): if not args: args = [] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = [('cnt_nombre_banco', operator, name), ('cnt_nombre_banco', operator, name)] else: domain = [ '|', '|', '|', ('cnt_nombre_banco', operator, name), ('codigo_sucursal', operator, name), ('cnt_nro_cuenta', operator, name), ('nombre_sucursal', operator, name) ] ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context) return self.name_get(cr, user, ids, context=context)
def on_change_model_id(self, cr, uid, ids, model_id, context=None): """Force domain for the `field_id` and `field_date_id` fields""" if not model_id: return { 'domain': { 'field_id': expression.FALSE_DOMAIN, 'field_date_id': expression.FALSE_DOMAIN } } model = self.pool['ir.model'].browse(cr, uid, model_id, context=context) model_fields_domain = [ '|', ('model_id', '=', model_id), ('model_id', 'in', model.inherited_model_ids.ids) ] model_date_fields_domain = expression.AND([[ ('ttype', 'in', ('date', 'datetime')) ], model_fields_domain]) return { 'domain': { 'field_id': model_fields_domain, 'field_date_id': model_date_fields_domain } }
def _search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None): """ Override that adds specific access rights of mail.message, to restrict messages to published messages for public users. """ if uid != SUPERUSER_ID: group_ids = self.pool.get('res.users').browse( cr, uid, uid, context=context).groups_id group_user_id = self.pool.get( "ir.model.data").get_object_reference(cr, uid, 'base', 'group_public')[1] if group_user_id in [group.id for group in group_ids]: args = expression.AND([[('website_published', '=', True)], list(args)]) return super(MailMessage, self)._search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count, access_rights_uid=access_rights_uid)
def mark_all_as_read(self, channel_ids=None, domain=None): """ Remove all needactions of the current partner. If channel_ids is given, restrict to messages written in one of those channels. """ partner_id = self.env.user.partner_id.id if domain is None: query = "DELETE FROM mail_message_res_partner_needaction_rel WHERE res_partner_id IN %s" args = [(partner_id,)] if channel_ids: query += """ AND mail_message_id in (SELECT mail_message_id FROM mail_message_mail_channel_rel WHERE mail_channel_id in %s)""" args += [tuple(channel_ids)] query += " RETURNING mail_message_id as id" self._cr.execute(query, args) self.invalidate_cache() ids = [m['id'] for m in self._cr.dictfetchall()] else: # not really efficient method: it does one db request for the # search, and one for each message in the result set to remove the # current user from the relation. msg_domain = [('needaction_partner_ids', 'in', partner_id)] if channel_ids: msg_domain += [('channel_ids', 'in', channel_ids)] unread_messages = self.search(expression.AND([msg_domain, domain])) unread_messages.sudo().write({'needaction_partner_ids': [(3, partner_id)]}) ids = unread_messages.mapped('id') notification = {'type': 'mark_as_read', 'message_ids': ids, 'channel_ids': channel_ids} self.env['bus.bus'].sendone((self._cr.dbname, 'res.partner', self.env.user.partner_id.id), notification) return ids
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): if not args: args = [] op = operator in [ 'like', 'ilike', '=', ] and operator or 'ilike' ident = name.isdigit() and int(name) or -1 domain = [ '|', '|', ('select_name', op, name), ('technical_name', op, name), ('identifier', '=', ident), ] domain = expression.AND([domain, args]) ids = self.search(cr, user, domain, limit=limit, context=context) return self.name_get(cr, user, ids, context=context)
def _query_kpi_data(self, date_from, date_to, base_domain): """Query mis.kpi.data over a time period. Returns {mis.report.kpi.expression: amount} """ dt_from = fields.Date.from_string(date_from) dt_to = fields.Date.from_string(date_to) # all data items within or overlapping [date_from, date_to] date_domain = [ ('date_from', '<=', date_to), ('date_to', '>=', date_from), ] domain = expression.AND([date_domain, base_domain]) res = defaultdict(float) res_avg = defaultdict(list) for item in self.search(domain): i_days, item_days = item._intersect_days(dt_from, dt_to) if item.kpi_expression_id.kpi_id.accumulation_method == ACC_SUM: # accumulate pro-rata overlap between item and reporting period res[item.kpi_expression_id] += item.amount * i_days / item_days elif item.kpi_expression_id.kpi_id.accumulation_method == ACC_AVG: # memorize the amount and number of days overlapping # the reporting period (used as weight in average) res_avg[item.kpi_expression_id].append((i_days, item.amount)) else: raise UserError( _("Unexpected accumulation method %s for %s.") % (item.kpi_expression_id.kpi_id.accumulation_method, item.name)) # compute weighted average for ACC_AVG for kpi_expression, amounts in res_avg.items(): res[kpi_expression] = \ sum(d * a for d, a in amounts) / sum(d for d, a in amounts) return res
def check_record_rule_cause_error(self, model_name, user, rule, mode="read"): """ Evaluate the rule to check whether it cause the access right error or not. This function is the combination of 2 functions: + domain_get + _check_record_rules_result_count """ model_pooler = self.pool[model_name] global_domains = [] # list of domains group_domains = {} # map: group -> list of domains rule_domain = rule.domain dom = expression.normalize_domain(rule_domain) for group in rule.groups: if group in user.groups_id: group_domains.setdefault(group, []).append(dom) if not rule.groups: global_domains.append(dom) # combine global domains and group domains if group_domains: group_domain = expression.OR(map(expression.OR, group_domains.values())) else: group_domain = [] domain = expression.AND(global_domains + [group_domain]) if domain: # _where_calc is called as superuser. This means that rules can # involve objects on which the real uid has no acces rights. # This means also there is no implicit restriction (e.g. an object # references another object the user can't see). query = self.pool.get(model_name)._where_calc(self._cr, SUPERUSER_ID, domain, active_test=False) where_clause, where_params, tables = query.where_clause, \ query.where_clause_params, query.tables if where_clause: where_clause = ' and ' + ' and '.join(where_clause) self._cr.execute( 'SELECT ' + model_pooler._table + '.id FROM ' + ','.join(tables) + ' WHERE ' + model_pooler._table + '.id IN %s' + where_clause, ([tuple(self._ids)] + where_params)) result_ids = [x['id'] for x in self._cr.dictfetchall()] ids, result_ids = set(self._ids), set(result_ids) missing_ids = ids - result_ids if missing_ids: # Attempt to distinguish record rule # restriction vs deleted records, # to provide a more specific error message - # check if the missinf self._cr.execute( 'SELECT id FROM ' + model_pooler._table + ' WHERE id IN %s', (tuple(missing_ids), )) # the missing ids are (at least partially) # hidden by access rules if self._cr.rowcount or mode not in ('read', 'unlink'): return True return False
def channel_search_to_join(self, name=None, domain=None): """ Return the channel info of the channel the current partner can join :param name : the name of the researched channels :param domain : the base domain of the research :returns dict : channel dict """ if not domain: domain = [] domain = expression.AND([[('channel_type', '=', 'channel')], [('channel_partner_ids', 'not in', [self.env.user.partner_id.id])], [('public', '!=', 'private')], domain]) if name: domain = expression.AND( [domain, [('name', 'ilike', '%' + name + '%')]]) return self.search(domain).read( ['name', 'public', 'uuid', 'channel_type'])
def view_report(self): report_domain = [] for data in self: if data.type == 'by_product': domain = [('product_id', '=', data.product_id.id)] report_domain = expression.AND([domain] + [report_domain]) elif data.type == 'by_category': domain = [('categ_id', 'child_of', data.product_categ_id.id)] report_domain = expression.AND([domain] + [report_domain]) elif data.type == 'by_products': products = [] for line in data.product_ids: products.append(line.product_id.id) domain = [('product_id', 'in', products)] report_domain = expression.AND([domain] + [report_domain]) if data.shop_id: domain = [('shop_id', '=', data.shop_id.id)] report_domain = expression.AND([domain] + [report_domain]) if data.partner_id: domain = [('partner_id', '=', data.partner_id.id)] report_domain = expression.AND([domain] + [report_domain]) if data.user_id: domain = [('user_id', '=', data.user_id.id)] report_domain = expression.AND([domain] + [report_domain]) if data.date_from: domain = [('date_invoice', '>=', data.date_from)] report_domain = expression.AND([domain] + [report_domain]) if data.date_to: domain = [('date_invoice', '<=', data.date_to)] report_domain = expression.AND([domain] + [report_domain]) self.env['m.report.view'].check_and_refresh_materialized_view( "product_sale_invoice_list") self.env['m.report.view'].check_and_refresh_materialized_view( "product_date_sold_returned_invoices") data_obj = self.pool.get('ir.model.data') model_data_id = self.env['ir.model.data']._get_id( 'poi_logistic_analysis_sale', 'view_product_date_sold_returned_invoices_graph') res_id = self.env['ir.model.data'].browse(model_data_id).res_id return { 'name': _('Sale Invoices Analysis'), 'domain': report_domain, 'view_type': 'form', 'view_mode': 'chart', 'res_model': 'product.date.sold.returned.invoices', 'view_id': res_id, 'context': {}, 'type': 'ir.actions.act_window' }
def name_search(self, cr, user, name, args=None, operator='ilike', context=None, limit=100): if not args: args = [] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = [('name', operator, name), ('description', operator, name)] else: domain = ['|', ('name', operator, name), ('description', operator, name)] ids = self.search(cr, user, expression.AND([domain, args]), limit=limit, context=context) return self.name_get(cr, user, ids, context=context)
def test_40_negating_long_expression(self): source = ['!','&',('user_id','=',4),('partner_id','in',[1,2])] expect = ['|',('user_id','!=',4),('partner_id','not in',[1,2])] self.assertEqual(expression.distribute_not(source), expect, "distribute_not on expression applied wrongly") pos_leaves = [[('a', 'in', [])], [('d', '!=', 3)]] neg_leaves = [[('a', 'not in', [])], [('d', '=', 3)]] source = expression.OR([expression.AND(pos_leaves)] * 1000) expect = source self.assertEqual(expression.distribute_not(source), expect, "distribute_not on long expression without negation operator should not alter it") source = ['!'] + source expect = expression.AND([expression.OR(neg_leaves)] * 1000) self.assertEqual(expression.distribute_not(source), expect, "distribute_not on long expression applied wrongly")
def open_po(self): """ This opens po view to view all generated po associated to the call for bids """ ActWindow = self.env['ir.actions.act_window'] res = ActWindow.for_xml_id('purchase', 'purchase_form_action') res['domain'] = expression.AND([safe_eval(res.get('domain', [])), [('requisition_id', 'in', self.ids)]]) return res
def name_search(self, name, args=None, operator='ilike', limit=100): args = args or [] if args is None: args = [] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = [('code', operator, name), ('name', operator, name)] else: domain = ['|', ('code', operator, name), ('name', operator, name)] recs = self.search(expression.AND([domain, args]), limit=limit) return recs.name_get()
def _compute_domain(self, cr, uid, model_name, mode="read", context=None): context = context or {} if mode not in self._MODES: raise ValueError('Invalid mode: %r' % (mode, )) if uid == SUPERUSER_ID: return None cr.execute( """SELECT r.id FROM ir_rule r JOIN ir_model m ON (r.model_id = m.id) WHERE m.model = %s AND r.active is True AND r.perm_""" + mode + """ AND (r.id IN (SELECT rule_group_id FROM rule_group_rel g_rel JOIN res_groups_users_rel u_rel ON (g_rel.group_id = u_rel.gid) WHERE u_rel.uid = %s) OR r.global)""", (model_name, uid)) rule_ids = [x[0] for x in cr.fetchall()] if rule_ids: # browse user as super-admin root to avoid access errors! user = self.pool.get('res.users').browse(cr, SUPERUSER_ID, uid) global_domains = [] # list of domains group_domains = {} # map: group -> list of domains context['_compute_domain_rules'] = [ ] #Used to show a comprensive rule error message for rule in self.browse(cr, SUPERUSER_ID, rule_ids): # read 'domain' as UID to have the correct eval context for the rule. rule_domain = self.read(cr, uid, rule.id, ['domain'])['domain'] dom = expression.normalize_domain(rule_domain) for group in rule.groups: if group in user.groups_id: group_domains.setdefault(group, []).append(dom) if not rule.groups: global_domains.append(dom) context['_compute_domain_rules'].append({ 'id': rule.id, 'name': rule.name, 'domain': dom, 'groups': [g.name for g in rule.groups], 'model': rule.model_id.name }) # combine global domains and group domains if group_domains: group_domain = expression.OR( map(expression.OR, group_domains.values())) else: group_domain = [] domain = expression.AND(global_domains + [group_domain]) return domain return []
def view_kardex_graph_stock(self): data = self.read()[0] report_domain = [] if data['date_from']: date_from = str(data['date_from']) domain = [('date', '>=', date_from + ' 00:00:00')] report_domain = expression.AND([domain] + [report_domain]) if data['date_to']: date_to = str(data['date_to']) domain = [('date', '<=', date_to + ' 23:59:59')] report_domain = expression.AND([domain] + [report_domain]) if data['product_id']: product_id = str(data['product_id'][0]) domain = [('product_id', '=', int(product_id))] report_domain = expression.AND([domain] + [report_domain]) if data['location_id']: location_id = str(data['location_id'][0]) domain = [('location_id', '=', int(location_id))] report_domain = expression.AND([domain] + [report_domain]) # self.env['m.report.view'].check_and_refresh_materialized_view("poi_report_kardex_inv") self.env['m.report.view'].check_and_refresh_materialized_view( "poi_stock_kardex_analysis") data_obj = self.pool.get('ir.model.data') model_data_id = self.env['ir.model.data']._get_id( 'poi_logistic_analysis_stock', 'view_poi_stock_kardex_analysis_graph') res_id = self.env['ir.model.data'].browse(model_data_id).res_id return { 'domain': report_domain, 'name': _('Stock Statistics'), 'view_type': 'form', 'view_mode': 'chart', 'res_model': 'poi.stock.kardex.analysis', 'view_id': res_id, 'context': {}, 'type': 'ir.actions.act_window' }
def search(self, args, offset=0, limit=None, order=None, count=False): """ Display only standalone contact matching ``args`` or having attached contact matching ``args`` """ ctx = self.env.context if (ctx.get('search_show_all_positions', {}).get('is_set') and not ctx['search_show_all_positions']['set_value']): args = expression.normalize_domain(args) attached_contact_args = expression.AND( (args, [('contact_type', '=', 'attached')])) attached_contacts = super(ResPartner, self).search(attached_contact_args) args = expression.OR(( expression.AND(([('contact_type', '=', 'standalone')], args)), [('other_contact_ids', 'in', attached_contacts.ids)], )) return super(ResPartner, self).search(args, offset=offset, limit=limit, order=order, count=count)
def _check_needaction_domain(self): for this in self: try: expression.AND([ this._eval_needaction_domain(), expression.TRUE_DOMAIN, ]) except Exception as ex: raise UserError( _('Cannot evaluate %s to a search domain:\n%s') % (self.needaction_domain, ex))
def get_mention_suggestions(self, search, limit=8): """ Return 'limit'-first channels' id, name and public fields such that the name matches a 'search' string. Exclude channels of type chat (DM), and private channels the current user isn't registered to. """ domain = expression.AND([[('name', 'ilike', search)], [('channel_type', '=', 'channel')], expression.OR( [[('public', '!=', 'private')], [('channel_partner_ids', 'in', [self.env.user.partner_id.id])]])]) return self.search_read(domain, ['id', 'name', 'public'], limit=limit)
def _create_or_combine_sharing_rule(self, cr, current_user, wizard_data, group_id, model_id, domain, restrict=False, rule_name=None, context=None): """Add a new ir.rule entry for model_id and domain on the target group_id. If ``restrict`` is True, instead of adding a rule, the domain is combined with AND operator with all existing rules in the group, to implement an additional restriction (as of 6.1, multiple rules in the same group are OR'ed by default, so a restriction must alter all existing rules) This is necessary because the personal rules of the user that is sharing are first copied to the new share group. Afterwards the filters used for sharing are applied as an additional layer of rules, which are likely to apply to the same model. The default rule algorithm would OR them (as of 6.1), which would result in a combined set of permission that could be larger than those of the user that is sharing! Hence we must forcefully AND the rules at this stage. One possibly undesirable effect can appear when sharing with a pre-existing group, in which case altering pre-existing rules would not be desired. This is addressed in the portal module. """ if rule_name is None: rule_name = _('Sharing filter created by user %s (%s) for group %s') % \ (current_user.name, current_user.login, group_id) rule_obj = self.pool.get('ir.rule') rule_ids = rule_obj.search(cr, UID_ROOT, [('groups', 'in', group_id), ('model_id', '=', model_id)]) if rule_ids: for rule in rule_obj.browse(cr, UID_ROOT, rule_ids, context=context): if rule.domain_force == domain: # don't create it twice! if restrict: continue else: _logger.debug("Ignoring sharing rule on model %s with domain: %s the same rule exists already", model_id, domain) return if restrict: # restricting existing rules is done by adding the clause # with an AND, but we can't alter the rule if it belongs to # other groups, so we duplicate if needed rule = self._check_personal_rule_or_duplicate(cr, group_id, rule, context=context) eval_ctx = rule_obj._eval_context_for_combinations() org_domain = expression.normalize_domain(eval(rule.domain_force, eval_ctx)) new_clause = expression.normalize_domain(eval(domain, eval_ctx)) combined_domain = expression.AND([new_clause, org_domain]) rule.write({'domain_force': combined_domain, 'name': rule.name + _('(Modified)')}) _logger.debug("Combining sharing rule %s on model %s with domain: %s", rule.id, model_id, domain) if not rule_ids or not restrict: # Adding the new rule in the group is ok for normal cases, because rules # in the same group and for the same model will be combined with OR # (as of v6.1), so the desired effect is achieved. rule_obj.create(cr, UID_ROOT, { 'name': rule_name, 'model_id': model_id, 'domain_force': domain, 'groups': [(4,group_id)] }) _logger.debug("Created sharing rule on model %s with domain: %s", model_id, domain)
def open_rfq(self): """ This opens rfq view to view all generated rfq/bids associated to the call for bids """ ActWindow = self.env['ir.actions.act_window'] res = ActWindow.for_xml_id('purchase', 'purchase_rfq') res['domain'] = expression.AND([safe_eval(res.get('domain', [])), [('requisition_id', 'in', self.ids)]]) # FIXME: need to disable create - temporarily set as invisible in view return res
def open_po(self, cr, uid, ids, context=None): """ This opens po view to view all generated po associated to the call for bids """ if context is None: context = {} res = self.pool.get('ir.actions.act_window').for_xml_id( cr, uid, 'purchase', 'purchase_form_action', context=context) res['domain'] = expression.AND( [eval(res.get('domain', [])), [('requisition_id', 'in', ids)]]) return res
def name_search(self, name, args=None, operator='ilike', limit=80): """ Returns a list of tupples containing id, name, as internally it is called {def name_get} result format: {[(id, name), (id, name), ...]} """ args = args or [] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = [('description', operator, name), ('name', operator, name)] else: domain = ['|', ('description', operator, name), ('name', operator, name)] taxes = self.search(expression.AND([domain, args]), limit=limit) return taxes.name_get()
def _search_custom(self, cr, user, args, offset=0, limit=None, order=None, context=None, count=False, access_rights_uid=None): """ Private implementation of search() method, allowing specifying the uid to use for the access right check. This is useful for example when filling in the selection list for a drop-down and avoiding access rights errors, by specifying ``access_rights_uid=1`` to bypass access rights check, but not ir.rules! This is ok at the security level because this method is private and not callable through XML-RPC. :param access_rights_uid: optional user ID to use when checking access rights (not for ir.rules, this is only for ir.model.access) """ if context is None: context = {} self.check_access_rights(cr, access_rights_uid or user, 'read') # For transient models, restrict access to the current user, except for the super-user if self.is_transient() and self._log_access and user != SUPERUSER_ID: args = expression.AND(([('create_uid', '=', user)], args or [])) query = self._where_calc(cr, user, args, context=context) self._apply_ir_rules(cr, user, query, 'read', context=context) order_by = self._generate_order_by(order, query) from_clause, where_clause, where_clause_params = query.get_sql() where_str = where_clause and (" WHERE %s" % where_clause) or '' if count: if context.get("load_count_stat"): self.refresh_stat(cr, from_clause.replace("\"", "")) query_str = 'SELECT id FROM ' + from_clause + where_str query_eval = cr.mogrify(query_str, where_clause_params) query_estimate = "select count_stat('%s')" % query_eval.replace("'", "''") cr.execute(query_estimate) res = cr.fetchone() else: query_str = 'SELECT count(1) FROM ' + from_clause + where_str cr.execute(query_str, where_clause_params) res = cr.fetchone() return res[0] limit_str = limit and ' limit %d' % limit or '' offset_str = offset and ' offset %d' % offset or '' query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + order_by + limit_str + offset_str cr.execute(query_str, where_clause_params) res = cr.fetchall() # TDE note: with auto_join, we could have several lines about the same result # i.e. a lead with several unread messages; we uniquify the result using # a fast way to do it while preserving order (http://www.peterbe.com/plog/uniqifiers-benchmark) def _uniquify_list(seq): seen = set() return [x for x in seq if x not in seen and not seen.add(x)] return _uniquify_list([x[0] for x in res])