odoo / openERP динамический домен one2many fields

Я хочу искать записи одного поля, которое зависит от других полей.
здесь мой код,

Родительский класс:

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    customer_product_ids = fields.One2many('product.product',
                           compute='_get_partner_products')
    order_line = fields.One2many('sale.order.line', 'order_id')

Дочерний класс:

class SaleOrderLine(models.Model):
    _inherit = 'sale.order.line'

    order_id = fields.Many2one('sale.order')
    product_id = fields.Many2one('product.product')

Вид

 <record id="view_ata_sale_order_form_inherit" model="ir.ui.view">
        <field name="name">view.ata.sale.order.form.inherit</field>
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form"/>
        <field name="arch" type="xml">
            <field name="partner_id" position="after">
                <field name="partner_channel_id" invisible="1"/>
                <field name="customer_product_ids"/>
            </field>
            <xpath expr="//tree/field[@name='product_id']" position="attributes">
                <attribute name="domain">[('id', 'in', [rec.id for rec in parent.customer_product_ids])]</attribute>
            </xpath>
        </field>
    </record>

По умолчанию клиент может видеть все определенные продукты.
В моем случае мне нужно отфильтровать продукты в зависимости от выбранного клиента.
Каждый клиент может иметь разные продукты списка или если они не классифицированы они могут видеть все продукты.

Я попробовал код выше, но получил ошибку:

Uncaught Error: Expected "]", got "(name)"

Я предполагаю, что ошибка исходит из этого кода:

<attribute name="domain">[('id', 'in', [rec.id for rec in parent.partner_product_ids])]</attribute>

мой вопрос,
возможно ли сделать понимание цикла python, как код выше (в поле зрения)?

Спасибо.


person yopiangi    schedule 08.12.2015    source источник


Ответы (3)


В вашем случае вам нужно использовать onchange и вернуть динамический домен в ваше поле one2many.

у вас должно быть что-то вроде этого:

@api.onchange('partner')
def onchange_partner(self):
    ids=search for products that have this partner
    then return some thing like this {'domain': {'Many2one or One2many': [('id', 'in', ids)}}

я не буду писать код за вас, поэтому вы должны найти onchange и применить его. Вы можете найти некоторую информацию здесь .

person Mostafa Mohamed    schedule 09.12.2015
comment
привет Мостафа, да, я новичок в разработке odoo, я попробовал ваше предложение, но оно не работает должным образом. Я опубликовал свое решение, и оно работает. :) - person yopiangi; 10.12.2015

Вы не можете вставить такой код туда. Я бы сделал по другому:

Изменить модель продукта, добавив своего покупателя

class Product(models.Model):
    _inherit = 'product.product'

    parent_id = fields.Many2one('res.partner')

тогда вид можно изменить гораздо проще:

<attribute name="domain">[('partner_id', '=', partner_id)]</attribute>

or

<attribute name="domain">[('partner_id', '=', parent.partner_id)]</attribute>

(в зависимости от того, где находится ваше поле product_id...

person Alessandro Ruffolo    schedule 09.12.2015
comment
Здравствуйте, Алессандро, спасибо за ваше предложение, я думаю, что нашел другой способ сделать это :) - person yopiangi; 10.12.2015

Привет Мостафа и Алессандро Руффоло

Большое спасибо за ответ на мой вопрос :) (# извините за поздний ответ)

Я попробовал решение Мостафы Мохамеда, но оно не повлияло на список продуктов (они продолжают отображать все продукты).
Что должны делать и возвращать методы onchange?

Вот мой код,

@api.multi
def onchange_partner_id(self, part):
    res = super(SaleOrder, self).onchange_partner_id(part)
    domain = [('active', '=', True), ('sale_ok', '=', True)]
    if part:
        partner = self.env['res.partner'].browse(part)
        if partner and partner.sales_channel_id:
            domain.append(('sales_channel_ids', '=',
                           partner.sales_channel_id.id))
    product_ids = self.env['product.product'].search(domain)
    res.update(domain={
        'order_line.product_id': ['id', 'in', [rec.id for rec in product_ids]]
    })
    return res  

Я пробовал другое решение, поэтому я переопределяю методы search_name и search в модели product.product, и это работает.

вот мой код,
1) наследует sale_view.xml

<xpath expr="//tree/field[@name='product_id']" position="attributes">
    <attribute name="domain">[
        ('sales_channel_ids', '=', parent.partner_channel_id),
        ('sale_ok', '=', True),
        ('active', '=', True)
    ]</attribute>
    <attribute name="context">{
        'partner_channel_id': parent.partner_channel_id,
        'partner_id': parent.partner_id,
        'quantity': product_uom_qty,
        'pricelist': parent.pricelist_id,
        'uom': product_uom,
        'company_id': parent.company_id
    }</attribute>
 </xpath>   

и метод переопределения
2) метод search_name:

@api.model
def name_search(self, name, args=None, operator='ilike', limit=100):
    if 'partner_channel_id' in self._context:
        target_domain = findDomain(args, 'sales_channel_ids')
        if len(target_domain) == 1:
            idx = target_domain.keys()[0]
            domain = target_domain.values()[0]
            if False in domain:
                args.pop(idx)
    return super(ProductProduct, self).name_search(name=name,
                                               args=args,
                                               operator=operator,
                                               limit=limit)   

3) метод поиска:

@api.model
def search(self, args, offset=0, limit=None, order=None, count=False):
    if 'partner_channel_id' in self._context:
        target_domain = findDomain(args, 'sales_channel_ids')
        if len(target_domain) == 1:
            idx = target_domain.keys()[0]
            domain = target_domain.values()[0]
            if False in domain:
                args.pop(idx)
    return super(ProductProduct, self).search(args=args,
                                          offset=offset,
                                          limit=limit,
                                          order=order,
                                          count=count)

Что я пытаюсь сделать здесь, так это то, что когда они обнаружили 'partner_channel_id' в контексте и домене, подобном этому ['sales_channel_ids', '=', False], я удалил этот домен и оставил остальные (клиент не имеет канала, может видеть все продукты, без фильтрации продуктов из них).

person yopiangi    schedule 10.12.2015
comment
конечно, это хорошее решение, я просто говорю вам, что мое решение короче и проще :) кроме того, я использовал его в своем собственном коде! - person Alessandro Ruffolo; 10.12.2015