Example #1
0
 def _search_full_name(self, operator, operand):
     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, pycompat.string_types):
         lst = False
         operand = [operand]
     where = []
     for group in operand:
         values = [v for v in group.split('/') if v]
         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
Example #2
0
 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'])
Example #3
0
 def get_website_translations(self, lang, mods=None):
     Modules = request.env['ir.module.module'].sudo()
     IrHttp = request.env['ir.http'].sudo()
     domain = IrHttp._get_translation_frontend_modules_domain()
     modules = Modules.search(
         expression.AND([domain, [('state', '=', 'installed')]])
     ).mapped('name')
     if mods:
         modules += mods
     return WebClient().translations(mods=modules, lang=lang)
Example #4
0
 def _search_rule(self, product_id, values, 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 values.get('warehouse_id', False):
         domain = expression.AND([['|', ('warehouse_id', '=', values['warehouse_id'].id), ('warehouse_id', '=', False)], domain])
     Pull = self.env['procurement.rule']
     res = self.env['procurement.rule']
     if values.get('route_ids', False):
         res = Pull.search(expression.AND([[('route_id', 'in', values['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 = Pull.search(expression.AND([[('route_id', 'in', product_routes.ids)], domain]), order='route_sequence, sequence', limit=1)
     if not res:
         warehouse_routes = values['warehouse_id'].route_ids
         if warehouse_routes:
             res = Pull.search(expression.AND([[('route_id', 'in', warehouse_routes.ids)], domain]), order='route_sequence, sequence', limit=1)
     return res
Example #5
0
 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)
Example #6
0
    def _gather(self,
                product_id,
                location_id,
                lot_id=None,
                package_id=None,
                owner_id=None,
                strict=False):
        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.sudo(self._uid).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])
Example #7
0
    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)]])
        fields = ['id', 'name', 'email']

        # Search users
        domain = expression.AND([[('user_ids.id', '!=', False)], 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]
Example #8
0
    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
        delete_mode = not self.env.user.share  # delete employee notifs, keep customer ones
        if not domain and delete_mode:
            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]))
            notifications = self.env['mail.notification'].sudo().search([
                ('mail_message_id', 'in', unread_messages.ids),
                ('res_partner_id', '=', self.env.user.partner_id.id),
                ('is_read', '=', False)])
            if delete_mode:
                notifications.unlink()
            else:
                notifications.write({'is_read': True})
            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
Example #9
0
    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)
Example #10
0
 def _change_model_id(self):
     """Force domain for the `field_id` and `field_date_id` fields"""
     if not self.model_id:
         return {
             'domain': {
                 'field_id': expression.FALSE_DOMAIN,
                 'field_date_id': expression.FALSE_DOMAIN
             }
         }
     model_fields_domain = [('store', '=', True), '|',
                            ('model_id', '=', self.model_id.id),
                            ('model_id', 'in',
                             self.model_id.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
         }
     }
Example #11
0
 def portal_message_fetch(self,
                          res_model,
                          res_id,
                          domain=False,
                          limit=10,
                          offset=0,
                          **kw):
     if not domain:
         domain = []
     # Only search into website_message_ids, so apply the same domain to perform only one search
     # extract domain from the 'website_message_ids' field
     field_domain = request.env[res_model]._fields[
         'website_message_ids'].domain
     domain += field_domain(
         request.env[res_model]) if callable(field_domain) else field_domain
     domain += [('res_id', '=', res_id)]
     # Check access
     Message = request.env['mail.message']
     if kw.get('token'):
         access_as_sudo = _has_token_access(res_model,
                                            res_id,
                                            token=kw.get('token'))
         if not access_as_sudo:  # if token is not correct, raise Forbidden
             raise Forbidden()
         # Non-employee see only messages with not internal subtype (aka, no internal logs)
         if not request.env['res.users'].has_group('base.group_user'):
             domain = expression.AND([[
                 '&', '&', ('subtype_id', '!=', False),
                 ('subtype_id.internal', '=', False)
             ], domain])
         Message = request.env['mail.message'].sudo()
     return {
         'messages':
         Message.search(domain, limit=limit,
                        offset=offset).portal_message_format(),
         'message_count':
         Message.search_count(domain)
     }
Example #12
0
    def _compute_domain(self, model_name, mode="read"):
        if mode not in self._MODES:
            raise ValueError('Invalid mode: %r' % (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():
            # 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
        return expression.AND(global_domains + [expression.OR(group_domains)])
Example #13
0
    def view(self, order_id, pdf=None, token=None, message=False, **post):
        # use sudo to allow accessing/viewing orders for public user
        # only if he knows the private token
        now = fields.Date.today()
        if token:
            Order = request.env['sale.order'].sudo().search([
                ('id', '=', order_id), ('access_token', '=', token)
            ])
        else:
            Order = request.env['sale.order'].search([('id', '=', order_id)])
        # Log only once a day
        if Order and request.session.get(
                'view_quote_%s' % Order.id) != now and request.env.user.share:
            request.session['view_quote_%s' % Order.id] = now
            body = _('Quotation viewed by customer')
            _message_post_helper(
                res_model='sale.order',
                res_id=Order.id,
                message=body,
                token=Order.access_token,
                message_type='notification',
                subtype="mail.mt_note",
                partner_ids=Order.user_id.sudo().partner_id.ids)
        if not Order:
            return request.render('website.404')

        # Token or not, sudo the order, since portal user has not access on
        # taxes, required to compute the total_amout of SO.
        order_sudo = Order.sudo()

        days = 0
        if order_sudo.validity_date:
            days = (fields.Date.from_string(order_sudo.validity_date) -
                    fields.Date.from_string(fields.Date.today())).days + 1
        if pdf:
            pdf = request.env.ref(
                'website_quote.report_web_quote').sudo().with_context(
                    set_viewport_size=True).render_qweb_pdf([order_sudo.id])[0]
            pdfhttpheaders = [('Content-Type', 'application/pdf'),
                              ('Content-Length', len(pdf))]
            return request.make_response(pdf, headers=pdfhttpheaders)
        transaction_id = request.session.get('quote_%s_transaction_id' %
                                             order_sudo.id)
        if not transaction_id:
            Transaction = request.env['payment.transaction'].sudo().search([
                ('reference', '=', order_sudo.name)
            ])
        else:
            Transaction = request.env['payment.transaction'].sudo().browse(
                transaction_id)
        values = {
            'quotation':
            order_sudo,
            'message':
            message and int(message) or False,
            'option':
            any(not x.line_id for x in order_sudo.options),
            'order_valid': (not order_sudo.validity_date)
            or (now <= order_sudo.validity_date),
            'days_valid':
            days,
            'action':
            request.env.ref('sale.action_quotations').id,
            'no_breadcrumbs':
            request.env.user.partner_id.commercial_partner_id
            not in order_sudo.message_partner_ids,
            'tx_id':
            Transaction.id if Transaction else False,
            'tx_state':
            Transaction.state if Transaction else False,
            'tx_post_msg':
            Transaction.acquirer_id.post_msg if Transaction else False,
            'payment_tx':
            Transaction,
            'need_payment':
            order_sudo.invoice_status == 'to invoice'
            and Transaction.state in ['draft', 'cancel', 'error'],
            'token':
            token,
            'return_url':
            '/shop/payment/validate',
            'bootstrap_formatting':
            True,
            'partner_id':
            order_sudo.partner_id.id,
        }

        if order_sudo.require_payment or values['need_payment']:
            domain = expression.AND(
                [[
                    '&', ('website_published', '=', True),
                    ('company_id', '=', order_sudo.company_id.id)
                ],
                 [
                     '|', ('specific_countries', '=', False),
                     ('country_ids', 'in',
                      [order_sudo.partner_id.country_id.id])
                 ]])
            acquirers = request.env['payment.acquirer'].sudo().search(domain)

            values['form_acquirers'] = [
                acq for acq in acquirers
                if acq.payment_flow == 'form' and acq.view_template_id
            ]
            values['s2s_acquirers'] = [
                acq for acq in acquirers if acq.payment_flow == 's2s'
                and acq.registration_view_template_id
            ]
            values['pms'] = request.env['payment.token'].search([
                ('partner_id', '=', order_sudo.partner_id.id),
                ('acquirer_id', 'in',
                 [acq.id for acq in values['s2s_acquirers']])
            ])

            for acq in values['form_acquirers']:
                acq.form = acq.render(
                    '/',
                    order_sudo.amount_total,
                    order_sudo.pricelist_id.currency_id.id,
                    values={
                        'return_url':
                        '/quote/%s/%s' %
                        (order_id, token) if token else '/quote/%s' % order_id,
                        'type':
                        'form',
                        'alias_usage':
                        _('If we store your payment information on our server, subscription payments will be made automatically.'
                          ),
                        'partner_id':
                        order_sudo.partner_id.id,
                    })
        history = request.session.get('my_quotes_history', [])
        values.update(get_records_pager(history, order_sudo))
        return request.render('website_quote.so_quotation', values)
Example #14
0
 def plan(self, domain):
     domain = expression.AND([domain, [('project_id', '!=', False)]
                              ])  # force timesheet and not AAL
     values = self._prepare_plan_values(domain)
     view = request.env.ref('sale_timesheet.timesheet_plan')
     return {'html_content': view.render(values)}
Example #15
0
 def name_search(self, name='', args=None, operator='ilike', limit=100):
     if not args:
         args = []
     if name:
         positive_operators = ['=', 'ilike', '=ilike', 'like', '=like']
         products = self.env['product.product']
         if operator in positive_operators:
             products = self.search([('default_code', '=', name)] + args,
                                    limit=limit)
             if not products:
                 products = self.search([('barcode', '=', name)] + args,
                                        limit=limit)
         if not products and operator not in expression.NEGATIVE_TERM_OPERATORS:
             # Do not merge the 2 next lines into one single search, SQL search performance would be abysmal
             # on a database with thousands of matching products, due to the huge merge+unique needed for the
             # OR operator (and given the fact that the 'name' lookup results come from the ir.translation table
             # Performing a quick memory merge of ids in Python will give much better performance
             products = self.search(args +
                                    [('default_code', operator, name)],
                                    limit=limit)
             if not limit or len(products) < limit:
                 # we may underrun the limit because of dupes in the results, that's fine
                 limit2 = (limit - len(products)) if limit else False
                 products += self.search(args +
                                         [('name', operator, name),
                                          ('id', 'not in', products.ids)],
                                         limit=limit2)
         elif not products and operator in expression.NEGATIVE_TERM_OPERATORS:
             domain = expression.OR([
                 [
                     '&', ('default_code', operator, name),
                     ('name', operator, name)
                 ],
                 [
                     '&', ('default_code', '=', False),
                     ('name', operator, name)
                 ],
             ])
             domain = expression.AND([args, domain])
             products = self.search(domain, limit=limit)
         if not products and operator in positive_operators:
             ptrn = re.compile('(\[(.*?)\])')
             res = ptrn.search(name)
             if res:
                 products = self.search(
                     [('default_code', '=', res.group(2))] + args,
                     limit=limit)
         # still no results, partner in context: search on supplier info as last hope to find something
         if not products and self._context.get('partner_id'):
             suppliers = self.env['product.supplierinfo'].search([
                 ('name', '=', self._context.get('partner_id')), '|',
                 ('product_code', operator, name),
                 ('product_name', operator, name)
             ])
             if suppliers:
                 products = self.search(
                     [('product_tmpl_id.seller_ids', 'in', suppliers.ids)],
                     limit=limit)
     else:
         products = self.search(args, limit=limit)
     return products.name_get()
Example #16
0
 def _analytic_compute_delivered_quantity_domain(self):
     domain = super(SaleOrderLine, self)._analytic_compute_delivered_quantity_domain()
     domain = expression.AND([domain, [('project_id', '=', False)]])
     timesheet_domain = self._timesheet_compute_delivered_quantity_domain()
     return expression.OR([domain, timesheet_domain])