4

I need applay domain on field product_id in purchase.order.line model, after call onchange method in purchase.order model.

Example:

_inherit = "purchase.order"

custom_id = fields.Many2one('custom.model', string='Custom') 

@api.onchange('custom_id')
def change_product(self):
    lst = [1,2,3]
    return {'domain': {'order_id.product_id': [('id', 'in', lst)]}}

This is original field where I want add my domain

product_id = fields.Many2one('product.product', string='Product',domain=[('purchase_ok', '=', True)], change_default=True, required=True)

I don't get any error but in product_id field show all data from database, not product where id 1,2,3 from above example.

user_odoo
  • 2,284
  • 34
  • 55

2 Answers2

0

write onchange function for product_id, instead of custom_id and return domain.

@api.onchange('product_id')
def change_product(self):
    lst = [1,2,3]
    return {'domain': {'product_id': [('id', 'in', lst)]}}

inside the onchange function consider the custom_id.

Hilar AK
  • 1,655
  • 13
  • 25
  • Tnx for help, product_id field depends custom_id. Eg. If choose custom_id (1) in lst get (Car 1, Car 2, Car 3), if select custom_id (2) fill product lst (Bike 1, Bike 2, Bike 3). onchange('custom_id') I need applay domain. – user_odoo Aug 07 '18 at 15:45
0

You have a little problem here: you can't set a domain for child relations IIRC.

What you can do is to create a related field on the child relation (here purchase.order.line and trigger the onchange on that.

class PurchaseOrder(models.Model):
    _inherit = "purchase.order"

    custom_id = fields.Many2one(
        comodel_name='custom.model', string='Custom')

class PurchaseOrderLine(models.Model):
    _inherit = "purchase.order.line"

    custom_id = fields.Many2one(
        comodel_name="custom.model", related="order_id.custom_id")

    @api.onchange('custom_id')
    def onchange_custom_id(self):
        lst = [1,2,3]
        return {'domain': {'product_id': [('id', 'in', lst)]}}

And some more information. Let me presume you have set custom_id on product variants (a) or on product categories (b). Just change the domain of product_id and use the domain operator '=?'. You won't need an onchange method for this solution, but you have to define custom_id in the view (invisible is possible, this is also a must have for the complete first solution)!

(a)

class PurchaseOrderLine(models.Model):
    _inherit = "purchase.order.line"

    custom_id = fields.Many2one(
        comodel_name="custom.model", related="order_id.custom_id")
    product_id = fields.Many2one(
        domain="[('purchase_ok', '=', True), ('custom_id', '=?', custom_id)]")

(b)

class PurchaseOrderLine(models.Model):
    _inherit = "purchase.order.line"

    custom_id = fields.Many2one(
        comodel_name="custom.model", related="order_id.custom_id")
    product_id = fields.Many2one(
        domain="[('purchase_ok', '=', True), ('categ_id.custom_id', '=?', custom_id)]")

If no custom_id is set the domain will read: product has to be purchasable AND True.

CZoellner
  • 13,553
  • 3
  • 25
  • 38
  • Tnx for nice example but with comodel name not working alweys get False. Here is what I need ---> Custom_id is actually contract_id in example below. I have custom module contract (contract.odoo) and contract.odoo.lines (where put product eg. Coca Cola, Fanta...) On purchase order (purchase.order) I'm add field contract_id after change that in product_id (purchase.order.line) I need load (Coca Cola, Fanta), after select other contract in field product_id i need load (eg. Audi, BMW...) How solve this issue? – user_odoo Aug 08 '18 at 06:52
  • The first solution should work without problems, just get the product IDs within the onchange method. The other examples would only work, if you had another one2many field, let's call it `contract_line_ids` on `product.product`. Then you could use `('contract_line_ids.contract_id', '=?', contract_id)` in the domain. – CZoellner Aug 08 '18 at 07:05