[FIX] mrp: orderpoint for manufacture not trigger twice
Usecase to reproduce: With BoM structure - Product A (RR 1-20) | Product B (MTO) | Product C (RR 5-50) | Product D (Buy) Launch the RR. The MO are: Current Behavior - Product A 20 - Product B 20 - Product C 50 - Product C 70 Expected Behavior - Product A 20 - Product B 20 - Product C 50 It happens because the MO are created as draft during the `_run_manufacture` and are confirm at the end of `_procure_orderpoint_confirm` in '_post_process_scheduler`. However at the first MO for product A, it creates a MO for product B and since it consumes product c, it checks if the orderpoint should be trigger. MO for product C still "draft" and the orderpoint forecast is now -20, so it will create a new procurement for product C with 70 units To fix it we take the MO draft linked to the orderpoint for the forecasted quantity. closes odoo/odoo#89079 X-original-commit: 199a0dd0f013655a3c2345a41bc7c721e09bfc68 Signed-off-by: Arnold Moyaux <arm@odoo.com> Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit is contained in:
@@ -50,7 +50,8 @@ class StockWarehouseOrderpoint(models.Model):
|
||||
for orderpoint in self
|
||||
if orderpoint.product_id in bom_kits
|
||||
}
|
||||
res = super(StockWarehouseOrderpoint, self.filtered(lambda p: p not in bom_kit_orderpoints))._quantity_in_progress()
|
||||
orderpoints_without_kit = self - self.env['stock.warehouse.orderpoint'].concat(*bom_kit_orderpoints.keys())
|
||||
res = super(StockWarehouseOrderpoint, orderpoints_without_kit)._quantity_in_progress()
|
||||
for orderpoint in bom_kit_orderpoints:
|
||||
dummy, bom_sub_lines = bom_kit_orderpoints[orderpoint].explode(orderpoint.product_id, 1)
|
||||
ratios_qty_available = []
|
||||
@@ -73,6 +74,18 @@ class StockWarehouseOrderpoint(models.Model):
|
||||
# (the quantity if we have received all in-progress components) - (the quantity using only available components)
|
||||
product_qty = min(ratios_total or [0]) - min(ratios_qty_available or [0])
|
||||
res[orderpoint.id] = orderpoint.product_id.uom_id._compute_quantity(product_qty, orderpoint.product_uom, round=False)
|
||||
|
||||
bom_manufacture = self.env['mrp.bom']._bom_find(orderpoints_without_kit.product_id, bom_type='normal')
|
||||
bom_manufacture = self.env['mrp.bom'].concat(*bom_manufacture.values())
|
||||
productions_group = self.env['mrp.production'].read_group(
|
||||
[('bom_id', 'in', bom_manufacture.ids), ('state', '=', 'draft'), ('orderpoint_id', 'in', orderpoints_without_kit.ids)],
|
||||
['orderpoint_id', 'product_qty', 'product_uom_id'],
|
||||
['orderpoint_id', 'product_uom_id'], lazy=False)
|
||||
for p in productions_group:
|
||||
uom = self.env['uom.uom'].browse(p['product_uom_id'][0])
|
||||
orderpoint = self.env['stock.warehouse.orderpoint'].browse(p['orderpoint_id'][0])
|
||||
res[orderpoint.id] += uom._compute_quantity(
|
||||
p['product_qty'], orderpoint.product_uom, round=False)
|
||||
return res
|
||||
|
||||
def _get_qty_multiple_to_order(self):
|
||||
|
||||
@@ -596,3 +596,83 @@ class TestProcurement(TestMrpCommon):
|
||||
self.assertEqual(manufacturing_order.product_qty, 10, 'The demand on the initial manufacturing order should not have been increased.')
|
||||
manufacturing_orders = self.env['mrp.production'].search([('product_id', '=', product.id)])
|
||||
self.assertEqual(len(manufacturing_orders), 2, 'A new MO should have been created for missing demand.')
|
||||
|
||||
def test_rr_with_dependance_between_bom(self):
|
||||
self.warehouse = self.env.ref('stock.warehouse0')
|
||||
route_mto = self.warehouse.mto_pull_id.route_id
|
||||
route_mto.active = True
|
||||
route_manufacture = self.warehouse.manufacture_pull_id.route_id
|
||||
product_1 = self.env['product.product'].create({
|
||||
'name': 'Product A',
|
||||
'type': 'product',
|
||||
'route_ids': [(6, 0, [route_manufacture.id])]
|
||||
})
|
||||
product_2 = self.env['product.product'].create({
|
||||
'name': 'Product B',
|
||||
'type': 'product',
|
||||
'route_ids': [(6, 0, [route_manufacture.id, route_mto.id])]
|
||||
})
|
||||
product_3 = self.env['product.product'].create({
|
||||
'name': 'Product B',
|
||||
'type': 'product',
|
||||
'route_ids': [(6, 0, [route_manufacture.id])]
|
||||
})
|
||||
product_4 = self.env['product.product'].create({
|
||||
'name': 'Product C',
|
||||
'type': 'consu',
|
||||
})
|
||||
|
||||
op1 = self.env['stock.warehouse.orderpoint'].create({
|
||||
'name': 'Product A',
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'product_id': product_1.id,
|
||||
'product_min_qty': 1,
|
||||
'product_max_qty': 20,
|
||||
})
|
||||
|
||||
op2 = self.env['stock.warehouse.orderpoint'].create({
|
||||
'name': 'Product B',
|
||||
'location_id': self.warehouse.lot_stock_id.id,
|
||||
'product_id': product_3.id,
|
||||
'product_min_qty': 5,
|
||||
'product_max_qty': 50,
|
||||
})
|
||||
|
||||
self.env['mrp.bom'].create({
|
||||
'product_id': product_1.id,
|
||||
'product_tmpl_id': product_1.product_tmpl_id.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'product_qty': 1,
|
||||
'consumption': 'flexible',
|
||||
'type': 'normal',
|
||||
'bom_line_ids': [(0, 0, {'product_id': product_2.id, 'product_qty': 1})]
|
||||
})
|
||||
|
||||
self.env['mrp.bom'].create({
|
||||
'product_id': product_2.id,
|
||||
'product_tmpl_id': product_2.product_tmpl_id.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'product_qty': 1,
|
||||
'consumption': 'flexible',
|
||||
'type': 'normal',
|
||||
'bom_line_ids': [(0, 0, {'product_id': product_3.id, 'product_qty': 1})]
|
||||
})
|
||||
|
||||
self.env['mrp.bom'].create({
|
||||
'product_id': product_3.id,
|
||||
'product_tmpl_id': product_3.product_tmpl_id.id,
|
||||
'product_uom_id': self.uom_unit.id,
|
||||
'product_qty': 1,
|
||||
'consumption': 'flexible',
|
||||
'type': 'normal',
|
||||
'bom_line_ids': [(0, 0, {'product_id': product_4.id, 'product_qty': 1})]
|
||||
})
|
||||
|
||||
(op1 | op2)._procure_orderpoint_confirm()
|
||||
mo1 = self.env['mrp.production'].search([('product_id', '=', product_1.id)])
|
||||
mo3 = self.env['mrp.production'].search([('product_id', '=', product_3.id)])
|
||||
|
||||
self.assertEqual(len(mo1), 1)
|
||||
self.assertEqual(len(mo3), 1)
|
||||
self.assertEqual(mo1.product_qty, 20)
|
||||
self.assertEqual(mo3.product_qty, 50)
|
||||
|
||||
Reference in New Issue
Block a user