def _build_channel_domain(self, base_domain, slide_type=None, my=False, **post): search_term = post.get('search') channel_tag_id = post.get('channel_tag_id') tags = self._extract_channel_tag_search(**post) domain = base_domain if search_term: domain = expression.AND([ domain, [ '|', ('name', 'ilike', search_term), ('description', 'ilike', search_term) ] ]) if channel_tag_id: domain = expression.AND( [domain, [('tag_ids', 'in', [channel_tag_id])]]) elif tags: domain = expression.AND([domain, [('tag_ids', 'in', tags.ids)]]) if slide_type and 'nbr_%s' % slide_type in request.env['slide.channel']: domain = expression.AND( [domain, [('nbr_%s' % slide_type, '>', 0)]]) if my: domain = expression.AND([ domain, [('partner_ids', '=', request.env.user.partner_id.id)] ]) return domain
def _search_rule(self, route_ids, product_id, warehouse_id, domain): """ First find a rule among the ones defined on the procurement group, then try on the routes defined for the product, finally fallback on the default behavior """ if warehouse_id: domain = expression.AND([[ '|', ('warehouse_id', '=', warehouse_id.id), ('warehouse_id', '=', False) ], domain]) Rule = self.env['stock.rule'] res = self.env['stock.rule'] if route_ids: res = Rule.search(expression.AND([[('route_id', 'in', route_ids.ids)], domain]), order='route_sequence, sequence', limit=1) if not res: product_routes = product_id.route_ids | product_id.categ_id.total_route_ids if product_routes: res = Rule.search(expression.AND([[ ('route_id', 'in', product_routes.ids) ], domain]), order='route_sequence, sequence', limit=1) if not res and warehouse_id: warehouse_routes = warehouse_id.route_ids if warehouse_routes: res = Rule.search(expression.AND([[ ('route_id', 'in', warehouse_routes.ids) ], domain]), order='route_sequence, sequence', limit=1) return res
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): args = args or [] if self.env.context.get('country_id'): args = expression.AND([ args, [('country_id', '=', self.env.context.get('country_id'))] ]) if operator == 'ilike' and not (name or '').strip(): first_domain = [] domain = [] else: first_domain = [('code', '=ilike', name)] domain = [('name', operator, name)] first_state_ids = self._search( expression.AND([first_domain, args]), limit=limit, access_rights_uid=name_get_uid) if first_domain else [] state_ids = first_state_ids + [ state_id for state_id in self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) if not state_id in first_state_ids ] return models.lazy_name_get( self.browse(state_ids).with_user(name_get_uid))
def _domain_move_lines_for_manual_reconciliation(self, account_id, partner_id=False, excluded_ids=None, search_str=False): """ Create domain criteria that are relevant to manual reconciliation. """ domain = [ '&', '&', ('reconciled', '=', False), ('account_id', '=', account_id), '|', ('move_id.state', '=', 'posted'), '&', ('move_id.state', '=', 'draft'), ('move_id.journal_id.post_at', '=', 'bank_rec') ] if partner_id: domain = expression.AND( [domain, [('partner_id', '=', partner_id)]]) if excluded_ids: domain = expression.AND([[('id', 'not in', excluded_ids)], domain]) if search_str: str_domain = self._domain_move_lines(search_str=search_str) domain = expression.AND([domain, str_domain]) # filter on account.move.line having the same company as the given account account = self.env['account.account'].browse(account_id) domain = expression.AND( [domain, [('company_id', '=', account.company_id.id)]]) return domain
def _get_channel_slides_base_domain(self, channel): """ base domain when fetching slide list data related to a given channel * website related domain, and restricted to the channel and is not a category slide (behavior is different from classic slide); * if publisher: everything is ok; * if not publisher but has user: either slide is published, either current user is the one that uploaded it; * if not publisher and public: published; """ base_domain = expression.AND([ request.website.website_domain(), [ '&', ('channel_id', '=', channel.id), ('is_category', '=', False) ] ]) if not channel.can_publish: if request.website.is_public_user(): base_domain = expression.AND( [base_domain, [('website_published', '=', True)]]) else: base_domain = expression.AND([ base_domain, [ '|', ('website_published', '=', True), ('user_id', '=', request.env.user.id) ] ]) return base_domain
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): if operator not in ('ilike', 'like', '=', '=like', '=ilike'): return super(AccountAnalyticAccount, self)._name_search(name, args, operator, limit, name_get_uid=name_get_uid) args = args or [] if operator == 'ilike' and not (name or '').strip(): domain = [] else: # search by partner separately because auto_join field can break searches partner_domain = [('partner_id.name', operator, name)] ids_partner = self._search(expression.AND([partner_domain, args]), limit=limit, access_rights_uid=name_get_uid) domain = ['|', '|', ('code', operator, name), ('name', operator, name), ('id', 'in', ids_partner)] analytic_account_ids = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) return self.browse(analytic_account_ids).name_get()
def _get_crm_utm_domain(self): """ We want all records that match the UTMs """ domain = [] if self.campaign_id: domain = expression.AND([domain, [('campaign_id', '=', self.campaign_id.id)]]) if self.source_id: domain = expression.AND([domain, [('source_id', '=', self.source_id.id)]]) if self.medium_id: domain = expression.AND([domain, [('medium_id', '=', self.medium_id.id)]]) if not domain: domain = expression.AND([domain, [(0, '=', 1)]]) return domain
def _check_current_contract(self): """ Two contracts in state [incoming | open | close] cannot overlap """ for contract in self.filtered( lambda c: c.state not in ['draft', 'cancel'] or c.state == 'draft' and c.kanban_state == 'done'): domain = [ ('id', '!=', contract.id), ('employee_id', '=', contract.employee_id.id), '|', ('state', 'in', ['open', 'close']), '&', ('state', '=', 'draft'), ('kanban_state', '=', 'done') # replaces incoming ] if not contract.date_end: start_domain = [] end_domain = [ '|', ('date_end', '>=', contract.date_start), ('date_end', '=', False) ] else: start_domain = [('date_start', '<=', contract.date_end)] end_domain = [ '|', ('date_end', '>', contract.date_start), ('date_end', '=', False) ] domain = expression.AND([domain, start_domain, end_domain]) if self.search_count(domain): raise ValidationError( _('An employee can only have one contract at the same time. (Excluding Draft and Cancelled contracts)' ))
def _domain_move_lines_for_reconciliation(self, st_line, aml_accounts, partner_id, excluded_ids=None, search_str=False, mode='rp'): def to_int(val): try: return int(val) except (ValueError, TypeError): return None domain = super()._domain_move_lines_for_reconciliation( st_line, aml_accounts, partner_id, excluded_ids=excluded_ids, search_str=search_str, mode=mode ) acc_props = ( "property_stock_account_input", "property_stock_account_output", "property_stock_account_input_categ_id", "property_stock_account_output_categ_id", ) acc_ids = [ (acc["value_reference"] or "").split(",")[-1] for acc in self.env["ir.property"] .sudo() .search([("name", "in", acc_props), ("value_reference", "!=", False)]) .read(["value_reference"]) if to_int((acc["value_reference"] or "").split(",")[-1]) ] if acc_ids: domain = expression.AND([domain, [("account_id.id", "not in", acc_ids)]]) return domain
def action_open_quants(self): location_domain = self._get_domain_locations()[0] domain = expression.AND([[('product_id', 'in', self.ids)], location_domain]) hide_location = not self.user_has_groups('stock.group_stock_multi_locations') hide_lot = all([product.tracking == 'none' for product in self]) self = self.with_context(hide_location=hide_location, hide_lot=hide_lot) # If user have rights to write on quant, we define the view as editable. if self.user_has_groups('stock.group_stock_manager'): self = self.with_context(inventory_mode=True) # Set default location id if multilocations is inactive if not self.user_has_groups('stock.group_stock_multi_locations'): user_company = self.env.company warehouse = self.env['stock.warehouse'].search( [('company_id', '=', user_company.id)], limit=1 ) if warehouse: self = self.with_context(default_location_id=warehouse.lot_stock_id.id) # Set default product id if quants concern only one product if len(self) == 1: self = self.with_context( default_product_id=self.id, single_product=True ) else: self = self.with_context(product_tmpl_id=self.product_tmpl_id.id) ctx = dict(self.env.context) ctx.update({'no_at_date': True}) return self.env['stock.quant'].with_context(ctx)._get_quants_action(domain)
def rating_get_repartition(self, add_stats=False, domain=None): """ get the repatition of rating grade for the given res_ids. :param add_stats : flag to add stat to the result :type add_stats : boolean :param domain : optional extra domain of the rating to include/exclude in repartition :return dictionnary if not add_stats, the dict is like - key is the rating value (integer) - value is the number of object (res_model, res_id) having the value otherwise, key is the value of the information (string) : either stat name (avg, total, ...) or 'repartition' containing the same dict if add_stats was False. """ base_domain = expression.AND( [self._rating_domain(), [('rating', '>=', 1)]]) if domain: base_domain += domain data = self.env['rating.rating'].read_group(base_domain, ['rating'], ['rating', 'res_id']) # init dict with all posible rate value, except 0 (no value for the rating) values = dict.fromkeys(range(1, 11), 0) values.update((d['rating'], d['rating_count']) for d in data) # add other stats if add_stats: rating_number = sum(values.values()) result = { 'repartition': values, 'avg': sum(float(key * values[key]) for key in values) / rating_number if rating_number > 0 else 0, 'total': sum(it['rating_count'] for it in data), } return result return values
def _make_infos(self, user, **kwargs): res = dict(kwargs) is_manager = request.env.user.has_group('lunch.group_lunch_manager') currency = user.company_id.currency_id res.update({ 'username': user.sudo().name, 'userimage': '/web/image?model=res.users&id=%s&field=image_128' % user.id, 'wallet': request.env['lunch.cashmove'].get_wallet_balance(user, False), 'is_manager': is_manager, 'locations': request.env['lunch.location'].search_read([], ['name']), 'currency': {'symbol': currency.symbol, 'position': currency.position}, }) user_location = user.last_lunch_location_id has_multi_company_access = not user_location.company_id or user_location.company_id.id in request._context.get('allowed_company_ids', request.env.company.ids) if not user_location or not has_multi_company_access: user.last_lunch_location_id = user_location = request.env['lunch.location'].search([], limit=1) alert_domain = expression.AND([ [('available_today', '=', True)], [('location_ids', 'in', user_location.id)], [('mode', '=', 'alert')], ]) res.update({ 'user_location': (user_location.id, user_location.name), 'alerts': request.env['lunch.alert'].search_read(alert_domain, ['message']), }) return res
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): # TDE FIXME: currently overriding the domain; however as it includes a # search on a m2o and one on a m2m, probably this will quickly become # difficult to compute - check if performance optimization is required if name and operator in ('=', 'ilike', '=ilike', 'like', '=like'): args = args or [] domain = [ '|', ('attribute_id', operator, name), ('value_ids', operator, name) ] attribute_ids = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) return models.lazy_name_get( self.browse(attribute_ids).with_user(name_get_uid)) return super(ProductTemplateAttributeLine, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid)
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): args = args or [] domain = [] if name: domain = ['|', ('name', operator, name), ('partner_ref', operator, name)] purchase_order_ids = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) return models.lazy_name_get(self.browse(purchase_order_ids).with_user(name_get_uid))
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): if operator not in ('ilike', 'like', '=', '=like', '=ilike'): return super(AccountAnalyticAccount, self)._name_search(name, args, operator, limit, name_get_uid=name_get_uid) args = args or [] if operator == 'ilike' and not (name or '').strip(): domain = [] else: # `partner_id` is in auto_join and the searches using ORs with auto_join fields doesn't work # we have to cut the search in two searches ... https://github.com/eagle/eagle/issues/25175 partner_ids = self.env['res.partner']._search( [('name', operator, name)], limit=limit, access_rights_uid=name_get_uid) domain = [ '|', '|', ('code', operator, name), ('name', operator, name), ('partner_id', 'in', partner_ids) ] analytic_account_ids = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) return models.lazy_name_get( self.browse(analytic_account_ids).with_user(name_get_uid))
def _get_domain_locations_new(self, location_ids, company_id=False, compute_child=True): operator = compute_child and 'child_of' or 'in' domain = company_id and ['&', ('company_id', '=', company_id)] or [] locations = self.env['stock.location'].browse(location_ids) # TDE FIXME: should move the support of child_of + auto_join directly in expression hierarchical_locations = locations if operator == 'child_of' else locations.browse() other_locations = locations - hierarchical_locations loc_domain = [] dest_loc_domain = [] # this optimizes [('location_id', 'child_of', hierarchical_locations.ids)] # by avoiding the ORM to search for children locations and injecting a # lot of location ids into the main query for location in hierarchical_locations: loc_domain = loc_domain and ['|'] + loc_domain or loc_domain loc_domain.append(('location_id.parent_path', '=like', location.parent_path + '%')) dest_loc_domain = dest_loc_domain and ['|'] + dest_loc_domain or dest_loc_domain dest_loc_domain.append(('location_dest_id.parent_path', '=like', location.parent_path + '%')) if other_locations: loc_domain = loc_domain and ['|'] + loc_domain or loc_domain loc_domain = loc_domain + [('location_id', operator, other_locations.ids)] dest_loc_domain = dest_loc_domain and ['|'] + dest_loc_domain or dest_loc_domain dest_loc_domain = dest_loc_domain + [('location_dest_id', operator, other_locations.ids)] usage = self._context.get('quantity_available_locations_domain') if usage: stock_loc_domain = expression.AND([domain + loc_domain, [('location_id.usage', 'in', usage)]]) else: stock_loc_domain = domain + loc_domain return ( stock_loc_domain, domain + dest_loc_domain + ['!'] + loc_domain if loc_domain else domain + dest_loc_domain, domain + loc_domain + ['!'] + dest_loc_domain if dest_loc_domain else domain + loc_domain )
def _compute_domain(self, model_name, mode="read"): if mode not in self._MODES: raise ValueError("Invalid mode: {!r}".format(mode)) if self._uid == SUPERUSER_ID: return None query = """ SELECT r.id FROM ir_rule r JOIN ir_model m ON (r.model_id=m.id) WHERE m.model=%s AND r.active AND r.perm_{mode} AND (r.id IN (SELECT rule_group_id FROM rule_group_rel rg JOIN res_groups_users_rel gu ON (rg.group_id=gu.gid) WHERE gu.uid=%s) OR r.global) """.format(mode=mode) self._cr.execute(query, (model_name, self._uid)) rule_ids = [row[0] for row in self._cr.fetchall()] if not rule_ids: return [] # browse user and rules as SUPERUSER_ID to avoid access errors! eval_context = self._eval_context() user_groups = self.env.user.groups_id global_domains = [] # list of domains group_domains = [] # list of domains for rule in self.browse(rule_ids).sudo(): # BEGIN redefined part of original _compute_domain of eagle/base/addons/ir/ir_rule. # have to redefine all method to take in account new ir.rule ``backend_behaviour`` setting dom = [] if not eval_context.get("website_id") and rule.backend_behaviour: dom = ([(1, "=", 1)] if rule.backend_behaviour == "true" else [(0, "=", 1)]) else: # evaluate the domain for the current user dom = (safe_eval(rule.domain_force, eval_context) if rule.domain_force else []) dom = expression.normalize_domain(dom) # END redefined part of original _compute_domain if not rule.groups: global_domains.append(dom) elif rule.groups & user_groups: group_domains.append(dom) # combine global domains and group domains if not group_domains: return expression.AND(global_domains) return expression.AND(global_domains + [expression.OR(group_domains)])
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None): args = args or [] if operator == 'ilike' and not (name or '').strip(): domain = [] else: domain = ['|', ('name', operator, name), ('driver_id.name', operator, name)] rec = self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid) return models.lazy_name_get(self.browse(rec).with_user(name_get_uid))
def _search(self, args, offset=0, limit=None, order=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 self.user_has_groups('base.group_public'): args = expression.AND([[('website_published', '=', True)], list(args)]) return super(MailMessage, self)._search(args, offset=offset, limit=limit, order=order, count=count, access_rights_uid=access_rights_uid)
def _get_records_from_sms(self, sms_sms_ids=None, additional_domain=None): if not self.ids and sms_sms_ids: domain = [('sms_sms_id_int', 'in', sms_sms_ids)] else: domain = [('id', 'in', self.ids)] if additional_domain: domain = expression.AND([domain, additional_domain]) return self.search(domain)
def _task_get_page_view_values(self, task, access_token, **kwargs): values = super(ProjectCustomerPortal, self)._task_get_page_view_values( task, access_token, **kwargs) domain = request.env[ 'account.analytic.line']._timesheet_get_portal_domain() domain = expression.AND([domain, [('task_id', '=', task.id)]]) timesheets = request.env['account.analytic.line'].sudo().search(domain) values['timesheets'] = timesheets return values
def _add_tracking(self, domain, website_track_values): """ Add the track and update the visitor""" domain = expression.AND([domain, [('visitor_id', '=', self.id)]]) last_view = self.env['website.track'].sudo().search(domain, limit=1) if not last_view or last_view.visit_datetime < datetime.now( ) - timedelta(minutes=30): website_track_values['visitor_id'] = self.id self.env['website.track'].create(website_track_values) self._update_visitor_last_visit()
def _get_contracts(self, date_from, date_to, states=['open'], kanban_state=False): """ Returns the contracts of the employee between date_from and date_to """ state_domain = [('state', 'in', states)] if kanban_state: state_domain = expression.AND( [state_domain, [('kanban_state', 'in', kanban_state)]]) return self.env['hr.contract'].search( expression.AND([[('employee_id', 'in', self.ids)], state_domain, [('date_start', '<=', date_to), '|', ('date_end', '=', False), ('date_end', '>=', date_from)]]))
def _prepare_badges_domain(self, **kwargs): """ Hook for other modules to restrict the badges showed on profile page, depending of the context """ domain = [('website_published', '=', True)] if 'badge_category' in kwargs: domain = expression.AND([[('challenge_ids.category', '=', kwargs.get('badge_category'))], domain]) return domain
def view_all_users_page(self, page=1, **searches): User = request.env['res.users'] dom = [('karma', '>', 1), ('website_published', '=', True)] # Searches search_term = searches.get('search') if search_term: dom = expression.AND([[ '|', ('name', 'ilike', search_term), ('company_id.name', 'ilike', search_term) ], dom]) user_count = User.sudo().search_count(dom) if user_count: page_count = math.ceil(user_count / self._users_per_page) pager = request.website.pager( url="/profile/users", total=user_count, page=page, step=self._users_per_page, scope=page_count if page_count < self._pager_max_pages else self._pager_max_pages) users = User.sudo().search(dom, limit=self._users_per_page, offset=pager['offset'], order='karma DESC') user_values = self._prepare_all_users_values(users) # Get karma position for users (only website_published) position_domain = [('karma', '>', 1), ('website_published', '=', True)] position_map = self._get_users_karma_position( position_domain, users.ids) for user in user_values: user['position'] = position_map.get(user['id'], 0) values = { 'top3_users': user_values[:3] if not search_term and page == 1 else None, 'users': user_values[3:] if not search_term and page == 1 else user_values, 'pager': pager } else: values = { 'top3_users': [], 'users': [], 'search': search_term, 'pager': dict(page_count=0) } return request.render("website_profile.users_page_main", values)
def _domain_product_id(self): if not self._is_inventory_mode(): return domain = [('type', '=', 'product')] if self.env.context.get('product_tmpl_id'): domain = expression.AND([ domain, [('product_tmpl_id', '=', self.env.context['product_tmpl_id'])] ]) return domain
def _notify_chat(self): records = self.search([('mode', '=', 'chat'), ('active', '=', True)]) today = fields.Date.today() now = fields.Datetime.now() for alert in records: notification_to = now.astimezone(pytz.timezone(alert.tz)).replace( second=0, microsecond=0, tzinfo=None) notification_from = notification_to - timedelta(minutes=5) send_at = datetime.combine( fields.Date.today(), float_to_time(alert.notification_time, alert.notification_moment)) if alert.available_today and send_at > notification_from and send_at <= notification_to: order_domain = [('state', '!=', 'cancelled')] if alert.location_ids.ids: order_domain = expression.AND([ order_domain, [('user_id.last_lunch_location_id', 'in', alert.location_ids.ids)] ]) if alert.recipients != 'everyone': weeks = 1 if alert.recipients == 'last_month': weeks = 4 else: # last_year weeks = 52 delta = timedelta(weeks=weeks) order_domain = expression.AND( [order_domain, [('date', '>=', today - delta)]]) orders = self.env['lunch.order'].search(order_domain).mapped( 'user_id') partner_ids = [user.partner_id.id for user in orders] if partner_ids: self.env['mail.thread'].message_notify( body=alert.message, partner_ids=partner_ids)
def get_mass_mailing_content(self, newsletter_id, **post): PopupModel = request.env['website.mass_mailing.popup'].sudo() data = self.is_subscriber(newsletter_id, **post) domain = expression.AND([request.website.website_domain(), [('mailing_list_id', '=', newsletter_id)]]) mass_mailing_popup = PopupModel.search(domain, limit=1) if mass_mailing_popup: data['popup_content'] = mass_mailing_popup.popup_content else: data.update(PopupModel.default_get(['popup_content'])) return data
def _get_number_of_attempts_lefts(self, partner, email, invite_token): """ Returns the number of attempts left. """ self.ensure_one() domain = [('survey_id', '=', self.id), ('test_entry', '=', False), ('state', '=', 'done')] if partner: domain = expression.AND( [domain, [('partner_id', '=', partner.id)]]) else: domain = expression.AND([domain, [('email', '=', email)]]) if invite_token: domain = expression.AND( [domain, [('invite_token', '=', invite_token)]]) return self.attempts_limit - self.env[ 'survey.user_input'].search_count(domain)
def _invoice_get_page_view_values(self, invoice, access_token, **kwargs): values = super(PortalAccount, self)._invoice_get_page_view_values( invoice, access_token, **kwargs) domain = request.env[ 'account.analytic.line']._timesheet_get_portal_domain() domain = expression.AND( [domain, [('timesheet_invoice_id', '=', invoice.id)]]) values['timesheets'] = request.env['account.analytic.line'].sudo( ).search(domain) return values