Search code examples
pythonodooodoo-11

Sending custom fields from MO BoM lines to PO order lines in Odoo


I'm trying to modify the BoM lines to add two custom fields: measure and unit of measure, like this: enter image description here

And I added the same for PO: enter image description here

It was the easy part, but, as you can see, PO order does not take the measure and unit of measure values from the BoM lines.

We need to take this values from BoM and split each item by measures too, not just by variants but also by measures because our vendors work with this.

How can we create this behavior? Which functions handle this?


Solution

  • We must take that values from the stock move from the given values.

    First, we will add both values in the respective models:

    class MrpBomLine(models.Model):
        _inherit = 'mrp.bom.line'
    
        item_num = fields.Integer(_('CAD Item Position'), help=_(
            "This is the item reference position into the CAD document that declares this BoM."))
        measure = fields.Char(_('Measure'))
        measure_uom_id = fields.Many2one(
            'product.uom',
            'Unit of Measure',
            help="Unit of Measure (Unit of Measure) is the unit of measurement for the products measure")
    
    class PurchaseOrderLine(models.Model):
        _inherit = 'purchase.order.line'
    
        measure = fields.Char(_('Measure'))
        measure_uom_id = fields.Many2one(
            'product.uom',
            'Unit of Measure',
            help="Unit of Measure (Unit of Measure) is the unit of measurement for the products measure"
        )
    

    We don't need to add any other thing in the mrp model.

    Second, we need to override the methods that prepare the purchase order lines, it is in the procurement rule. So, we inherit the procurement rule's model:

    class ProcurementRule(models.Model):
        _inherit = 'procurement.rule'
    

    We continue with the prepare function:

    @api.multi
    def _prepare_purchase_order_line(
            self, product_id, product_qty, product_uom, values, po, supplier
    ):
        result = super(ProcurementRule, self)._prepare_purchase_order_line(
            product_id, product_qty, product_uom, values, po, supplier
        )
        if values.get('move_dest_ids', False):
            result['measure'] = values['move_dest_ids'].bom_line_id.measure
            result['measure_uom_id'] = values['move_dest_ids'].bom_line_id.measure_uom_id.id
    
        return result
    

    We don't need to add the custom fields to the stock move or other function, this is because of Odoo handle creation using a data dictionary, in this case, it is values, inside of this value we can find all related variables and fields, bom.line variables also, where we included the custom fields.

    Until here, we solved the problem of taking the information from bom.line to purchase.order.

    Now, we need to avoid duplicates in the purchase order, for that we will modify the _run_buy function:

        # Create Line
        po_line = False
    
        for line in po.order_line:
            if line.product_id == product_id and \
                    line.product_uom == product_id.uom_po_id and \
                    values.get('move_dest_ids', False) and \
                    line.measure == values['move_dest_ids'].bom_line_id.measure and \
                    line.measure_uom_id.id == values['move_dest_ids'].bom_line_id.measure_uom_id.id:
                if line._merge_in_existing_line(
                        product_id, product_qty, product_uom,
                        location_id, name, origin, values
                ):
                    vals = self._update_purchase_order_line(
                        product_id, product_qty, product_uom,
                        values, line, partner
                    )
                    po_line = line.write(vals)
                    break
    

    We check first if the move_dest_ids key exists; after, we check that the product in the order line has the same measure that the product in the BoM line, and finally we check if the measure's unit of measure is the same. Just that.

    In this way we have added two custom fields in the Bom Line model and that the values of these fields are transferred from one model to another with the minimum code necessary and intervening as little as possible in the system flow.