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 _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'), ] domain = expression.AND([domain, [('balance', '!=', 0.0)]]) 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_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 action_time_off_analysis(self): domain = [('holiday_type', '=', 'employee')] if self.env.context.get('active_ids'): domain = expression.AND([ domain, [('employee_id', 'in', self.env.context.get('active_ids', []))] ]) return { 'name': _('Time Off Analysis'), 'type': 'ir.actions.act_window', 'res_model': 'hr.leave.report', 'view_mode': 'tree,form,pivot', 'search_view_id': self.env.ref('hr_holidays.view_hr_holidays_filter_report').id, 'domain': domain, 'context': { 'search_default_group_type': True, 'search_default_year': True } }
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/harpiya/harpiya/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 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 _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') and c.employee_id): 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 _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 _name_search(self, name='', args=None, operator='ilike', limit=100, name_get_uid=None): """ For expense, we want to show all sales order but only their name_get (no ir.rule applied), this is the only way to do it. """ if self._context.get('sale_expense_all_order'): domain = expression.AND([ args or [], [ '&', ('state', '=', 'sale'), ('company_id', 'in', self.env.companies.ids) ] ]) return super(SaleOrder, self.sudo())._name_search(name=name, args=domain, operator=operator, limit=limit, name_get_uid=SUPERUSER_ID) return super(SaleOrder, self)._name_search(name=name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid)
def _timesheet_get_portal_domain(self): """ Only the timesheets with a product invoiced on delivered quantity are concerned. since in ordered quantity, the timesheet quantity is not invoiced, thus there is no meaning of showing invoice with ordered quantity. """ domain = super(AccountAnalyticLine, self)._timesheet_get_portal_domain() return expression.AND([domain, [('timesheet_invoice_type', 'in', ['billable_time', 'non_billable'])]])
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): 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 _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 _compute_rating_stats(self): """ Compute avg and count in one query, as thoses fields will be used together most of the time. """ domain = expression.AND([self._rating_domain(), [('rating', '>=', RATING_LIMIT_MIN)]]) read_group_res = self.env['rating.rating'].read_group(domain, ['rating:avg'], groupby=['res_id'], lazy=False) # force average on rating column mapping = {item['res_id']: {'rating_count': item['__count'], 'rating_avg': item['rating']} for item in read_group_res} for record in self: record.rating_count = mapping.get(record.id, {}).get('rating_count', 0) record.rating_avg = mapping.get(record.id, {}).get('rating_avg', 0)
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 _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 _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 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 _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 get_translation_frontend_modules(self): Modules = request.env['ir.module.module'].sudo() extra_modules_domain = self._get_translation_frontend_modules_domain() extra_modules_name = self._get_translation_frontend_modules_name() if extra_modules_domain: new = Modules.search( expression.AND([extra_modules_domain, [('state', '=', 'installed')]]) ).mapped('name') extra_modules_name += new return extra_modules_name
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 _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
def _get_inheriting_views_arch_domain(self, view_id, model): domain = super(View, self)._get_inheriting_views_arch_domain(view_id, model) current_website = self._get_inheriting_views_arch_website(view_id) website_views_domain = current_website.website_domain() # when rendering for the website we have to include inactive views # we will prefer inactive website-specific views over active generic ones if current_website: domain = [leaf for leaf in domain if 'active' not in leaf] return expression.AND([website_views_domain, 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 _gather(self, product_id, location_id, lot_id=None, package_id=None, owner_id=None, strict=False): self.env['stock.quant'].flush( ['location_id', 'owner_id', 'package_id', 'lot_id', 'product_id']) self.env['product.product'].flush(['virtual_available']) removal_strategy = self._get_removal_strategy(product_id, location_id) removal_strategy_order = self._get_removal_strategy_order( removal_strategy) domain = [ ('product_id', '=', product_id.id), ] if not strict: if lot_id: domain = expression.AND([[('lot_id', '=', lot_id.id)], domain]) if package_id: domain = expression.AND([[('package_id', '=', package_id.id)], domain]) if owner_id: domain = expression.AND([[('owner_id', '=', owner_id.id)], domain]) domain = expression.AND([[('location_id', 'child_of', location_id.id)], domain]) else: domain = expression.AND([[('lot_id', '=', lot_id and lot_id.id or False)], domain]) domain = expression.AND([[ ('package_id', '=', package_id and package_id.id or False) ], domain]) domain = expression.AND([[ ('owner_id', '=', owner_id and owner_id.id or False) ], domain]) domain = expression.AND([[('location_id', '=', location_id.id)], domain]) # Copy code of _search for special NULLS FIRST/LAST order self.check_access_rights('read') query = self._where_calc(domain) self._apply_ir_rules(query, 'read') from_clause, where_clause, where_clause_params = query.get_sql() where_str = where_clause and (" WHERE %s" % where_clause) or '' query_str = 'SELECT "%s".id FROM ' % self._table + from_clause + where_str + " ORDER BY " + removal_strategy_order self._cr.execute(query_str, where_clause_params) res = self._cr.fetchall() # No uniquify list necessary as auto_join is not applied anyways... return self.browse([x[0] for x in res])
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 open_at_date(self): tree_view_id = self.env.ref('stock.view_stock_product_tree').id form_view_id = self.env.ref( 'stock.product_form_view_procurement_button').id domain = [('type', '=', 'product')] product_id = self.env.context.get('product_id', False) product_tmpl_id = self.env.context.get('product_tmpl_id', False) if product_id: domain = expression.AND([domain, [('id', '=', product_id)]]) elif product_tmpl_id: domain = expression.AND( [domain, [('product_tmpl_id', '=', product_tmpl_id)]]) # We pass `to_date` in the context so that `qty_available` will be computed across # moves until date. action = { 'type': 'ir.actions.act_window', 'views': [(tree_view_id, 'tree'), (form_view_id, 'form')], 'view_mode': 'tree,form', 'name': _('Products'), 'res_model': 'product.product', 'domain': domain, 'context': dict(self.env.context, to_date=self.inventory_datetime), } return action
def get_mention_suggestions(self, search, limit=8): """ Return 'limit'-first partners' id, name and email such that the name or email matches a 'search' string. Prioritize users, and then extend the research to all partners. """ search_dom = expression.OR([[('name', 'ilike', search)], [('email', 'ilike', search)]]) search_dom = expression.AND([[('active', '=', True)], search_dom]) fields = ['id', 'name', 'email'] # Search users domain = expression.AND([[('user_ids.id', '!=', False), ('user_ids.active', '=', True)], search_dom]) users = self.search_read(domain, fields, limit=limit) # Search partners if less than 'limit' users found partners = [] if len(users) < limit: partners = self.search_read(search_dom, fields, limit=limit) # Remove duplicates partners = [ p for p in partners if not len([u for u in users if u['id'] == p['id']]) ] return [users, partners]
def _compute_domain(self, model_name, mode="read"): rules = self._get_rules(model_name, mode=mode) if not rules: 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 rules.sudo(): # 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) 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)])