[IMP] stock: replenishment using qty from the BoM

The replenishement creation currently calculates the quantity to order
using a default multiple quantity of 1. In case of manufacturing route,
we want to calculate the multiple quantity according to the quantity
produced in the BoMs.

closes odoo/odoo#62766

Signed-off-by: Rémy Voet <ryv-odoo@users.noreply.github.com>
This commit is contained in:
Nicolas Pierre
2021-02-18 11:51:18 +00:00
parent f8faed2f43
commit fd19b0d7a2
4 changed files with 73 additions and 2 deletions
+10
View File
@@ -75,6 +75,16 @@ class StockWarehouseOrderpoint(models.Model):
res[orderpoint.id] = orderpoint.product_id.uom_id._compute_quantity(product_qty, orderpoint.product_uom, round=False)
return res
def _get_qty_multiple_to_order(self):
""" Calculates the minimum quantity that can be ordered according to the qty and UoM of the BoM
"""
self.ensure_one()
qty_multiple_to_order = super()._get_qty_multiple_to_order()
if 'manufacture' in self.rule_ids.mapped('action'):
bom = self.env['mrp.bom']._bom_find(product=self.product_id, bom_type='normal')
return bom.product_uom_id._compute_quantity(bom.product_qty, self.product_uom)
return qty_multiple_to_order
def _set_default_route_id(self):
route_id = self.env['stock.rule'].search([
('action', '=', 'manufacture')
+48
View File
@@ -835,3 +835,51 @@ class TestBoM(TestMrpCommon):
line.product_uom_id = uom_unit
line.product_qty = 5
bom_finished = bom_finished.save()
def test_replenishment(self):
""" Tests the auto generation of manual orderpoints.
The multiple quantity of the orderpoint should be the
quantity of the BoM in the UoM of the product.
"""
uom_kg = self.env.ref('uom.product_uom_kgm')
uom_gram = self.env.ref('uom.product_uom_gram')
product_gram = self.env['product.product'].create({
'name': 'Product sold in grams',
'type': 'product',
'uom_id': uom_gram.id,
'uom_po_id': uom_gram.id,
})
# We create a BoM that manufactures 2kg of product
self.env['mrp.bom'].create({
'product_id': product_gram.id,
'product_tmpl_id': product_gram.product_tmpl_id.id,
'product_uom_id': uom_kg.id,
'product_qty': 2.0,
'type': 'normal',
})
# We create a delivery order of 2300 grams
picking_form = Form(self.env['stock.picking'])
picking_form.picking_type_id = self.env.ref('stock.picking_type_out')
with picking_form.move_ids_without_package.new() as move:
move.product_id = product_gram
move.product_uom_qty = 2300.0
customer_picking = picking_form.save()
customer_picking.action_confirm()
# We check the created orderpoint without manufacturing route manufacturing
self.env['stock.warehouse.orderpoint']._get_orderpoint_action()
self.env['stock.warehouse.orderpoint']._get_orderpoint_action()
orderpoint = self.env['stock.warehouse.orderpoint'].search([('product_id', '=', product_gram.id)])
self.assertEqual(orderpoint.qty_multiple, 0.0)
self.assertEqual(orderpoint.qty_to_order, 2300.0)
# We select the manufacturing route and check the impact on the quantities
manufacturing_route_id = self.ref('mrp.route_warehouse0_manufacture')
manufacturing_route = self.env['stock.location.route'].search([('id', '=', manufacturing_route_id)])
orderpoint_form = Form(orderpoint)
orderpoint_form.route_id = manufacturing_route
orderpoint_form.save()
self.assertEqual(orderpoint.qty_multiple, 2000.0)
self.assertEqual(orderpoint.qty_to_order, 4000.0)
+13 -2
View File
@@ -200,6 +200,11 @@ class StockWarehouseOrderpoint(models.Model):
('company_id', '=', self.company_id.id)
], limit=1)
@api.onchange('route_id')
def _onchange_route_id(self):
if self.route_id:
self.qty_multiple = self._get_qty_multiple_to_order()
def write(self, vals):
if 'company_id' in vals:
for orderpoint in self:
@@ -259,6 +264,12 @@ class StockWarehouseOrderpoint(models.Model):
qty_to_order += orderpoint.qty_multiple - remainder
orderpoint.qty_to_order = qty_to_order
def _get_qty_multiple_to_order(self):
""" Calculates the minimum quantity that can be ordered according to the PO UoM or BoM
"""
self.ensure_one()
return 0
def _set_default_route_id(self):
""" Write the `route_id` field on `self`. This method is intendend to be called on the
orderpoints generated when openning the replenish report.
@@ -358,8 +369,8 @@ class StockWarehouseOrderpoint(models.Model):
orderpoints = self.env['stock.warehouse.orderpoint'].with_user(SUPERUSER_ID).create(orderpoint_values_list)
for orderpoint in orderpoints:
orderpoint.route_id = orderpoint.product_id.route_ids[:1]
orderpoints.filtered(lambda o: not o.route_id)._set_default_route_id()
orderpoint.route_id = orderpoint.product_id.route_ids[:1] or orderpoint._set_default_route_id()
orderpoint.qty_multiple = orderpoint._get_qty_multiple_to_order()
return action
@api.model
@@ -153,6 +153,8 @@
<group>
<group>
<field name="active" invisible="1"/>
<field name="allowed_route_ids" invisible="1"/>
<field name="route_id" invisible="1"/>
<field name="product_id"/>
<label for="product_min_qty"/>
<div class="o_row">