Search code examples
pythonodoo-13

Product filter with stock quantity in sale order line in odoo


enter image description here

class sale_product_filter(models.Model):
    _inherit= "sale.order.line"
    def _get_custom_domain(self):
        return [('categ_id.branch_id','=',self.env.user.branch_id.id)]
    product_id = fields.Many2one(domain= lambda self: self._get_custom_domain())
<record id="sale_order_form_inherit" model="ir.ui.view">
        <field name="name">sale.order.form.inherit</field> 
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form"/>
        <field name="priority" eval="8"/>
        <field name="arch" type="xml">
            <xpath expr="//field[@name='order_line']/tree/field[@name='product_id']" position="attributes">
                <attribute name="domain"/>
            </xpath>
        </field>
    </record>
<record id="rent_order_form_inherit" model="ir.ui.view">
        <field name="name">sale.order.form.inherit</field> 
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale_renting.rental_order_primary_form_view"/>
        <field name="priority" eval="8"/>
        <field name="arch" type="xml">
            <xpath expr="//field[@name='order_line']/tree/field[@name='product_id']" position="attributes">
                <attribute name="domain"/>
            </xpath>
        </field>
    </record>

I want to filter products in the sale order line. The current login user has his own warehouse with many products. I have many warehouses for many users.So, I want to display only the login user's warehouse products in the sale order line.

How can I do that?Every user has branch field and warehouse has branch field.When I add product in sale order line,I want to display only product that is in warehouse which branch is same with current user's branch and product quantity in warehouse is greater than 0.


Solution

  • Replace the default product_id domain with a computed domain to include the current user branch.

    The following example defines a computed domain to filter products and display only the products which are in the same branch with the current user.

    class SaleOrderLine(models.Model):
        _inherit = 'sale.order.line'
    
        def _get_custom_domain(self):
            return [('categ_id.branch_id', '=', self.env.user.branch_id.id)]
    
        product_id = fields.Many2one(domain=lambda self: self._get_custom_domain())
    

    Inherit the form view and replace the product_id domain:

    <record id="view_order_form" model="ir.ui.view">
            <field name="name">sale.order.form</field>
            <field name="model">sale.order</field>
            <field name="inherit_id" ref="sale.view_order_form"/>
            <field name="arch" type="xml">
              <xpath expr="//tree/field[@name='product_id']" position="attributes">
                  <attribute name="domain"/>
              </xpath>
            </field>
        </record>  
    

    You can compute the product available quantity in a specific warehouse by specifying the warehouse in the context:

    product_obj.with_context(warehouse=warehouse_id.id).browse(product_id).qty_available
    

    Search for products with quantity > 0 then use id field in the domain:

    [('id', 'in', filtered_product_ids)]
    

    Example:

    def _get_custom_domain(self):
        warehouse_id = self.env['stock.warehouse'].search([('branch_id', '=', self.env.user.branch_id.id)])
        product_ids = self.env['product.product'].with_context(warehouse=warehouse_id.ids).search([]).filtered(lambda p:p.qty_available > 0)
        return [('id', 'in', product_ids.ids)]
    

    Edit: Customize the domain from the action

    Try to add an additional domain parameter to the action context:

    'additional_domain': [('sale_ok', '=', True)
    

    Then add it to the computed domain if it is available in action context:

    return [('id', 'in', product_ids.ids)] + self.env.context.get('additional_domain', [])
    

    Edit: inherit quotations action to alter the context

    <record id="sale.action_quotations_with_onboarding" model="ir.actions.act_window">
        <field name="context">{'search_default_my_quotation': 1, 'additional_domain': [('sale_ok', '=', True)]}</field>
    </record>