[FIX] mrp: manual consumption wrong when backorder/split/merge

Fix the isuue that manual consumption is not correctly calculated when
backorder/split/merge.

closes odoo/odoo#115429

X-original-commit: d72ddd80d8a6aaa808c07db685972a1c05e8d6a4
Signed-off-by: Tiffany Chang <tic@odoo.com>
Signed-off-by: Yuchen Huang (yhu) <yhu@odoo.com>
This commit is contained in:
yhu-odoo
2023-03-16 09:37:14 +01:00
parent 360c48299a
commit 129f3d949d
3 changed files with 118 additions and 3 deletions
+1
View File
@@ -1040,6 +1040,7 @@ class MrpProduction(models.Model):
'warehouse_id': source_location.warehouse_id.id,
'group_id': self.procurement_group_id.id,
'propagate_cancel': self.propagate_cancel,
'manual_consumption': self.env['stock.move']._determine_is_manual_consumption(product_id, self, bom_line),
}
return data
+11 -3
View File
@@ -149,8 +149,7 @@ class StockMove(models.Model):
for move in self:
if move.state != 'draft':
continue
move.manual_consumption = (move.has_tracking != 'none' and not move.raw_material_production_id.use_auto_consume_components_lots) or \
(move.has_tracking == 'none' and move.bom_line_id.manual_consumption)
move.manual_consumption = move._is_manual_consumption()
@api.depends('bom_line_id')
def _compute_description_bom_line(self):
@@ -444,7 +443,7 @@ class StockMove(models.Model):
'state': 'confirmed',
'reservation_date': self.reservation_date,
'date_deadline': self.date_deadline,
'manual_consumption': self.bom_line_id.manual_consumption or self.product_id.tracking != 'none',
'manual_consumption': self._is_manual_consumption(),
'move_orig_ids': [Command.link(m.id) for m in self.mapped('move_orig_ids')],
'move_dest_ids': [Command.link(m.id) for m in self.mapped('move_dest_ids')],
'procure_method': self.procure_method,
@@ -593,3 +592,12 @@ class StockMove(models.Model):
'res_id': source.id,
}
return res
def _is_manual_consumption(self):
self.ensure_one()
return self._determine_is_manual_consumption(self.product_id, self.raw_material_production_id, self.bom_line_id)
@api.model
def _determine_is_manual_consumption(self, product, production, bom_line):
return (product.product_tmpl_id.tracking != 'none' and not production.use_auto_consume_components_lots) or \
(product.product_tmpl_id.tracking == 'none' and bom_line and bom_line.manual_consumption)
+106
View File
@@ -1,6 +1,7 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
# -*- coding: utf-8 -*-
from odoo.addons.mrp.tests.common import TestMrpCommon
from odoo.tests import tagged, Form, HttpCase
@@ -81,3 +82,108 @@ class TestTourManualConsumption(HttpCase):
self.assertEqual(move_nt.manual_consumption, False)
self.assertEqual(move_sn.manual_consumption, True)
self.assertEqual(move_lot.manual_consumption, True)
class TestManualConsumption(TestMrpCommon):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.stock_location = cls.env.ref('stock.stock_location_stock')
def test_manual_consumption_backorder_00(self):
"""Test when use_auto_consume_components_lots is not set, manual consumption
of the backorder is correctly set.
"""
mo, _, _final, c1, c2 = self.generate_mo('none', 'lot', 'none', qty_final=2)
self.assertTrue(mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
lot = self.env['stock.lot'].create({
'name': 'lot',
'product_id': c1.id,
'company_id': self.env.company.id,
})
self.env['stock.quant']._update_available_quantity(c1, self.stock_location, 8, lot_id=lot)
self.env['stock.quant']._update_available_quantity(c2, self.stock_location, 2)
mo.action_assign()
mo_form = Form(mo)
mo_form.qty_producing = 1
mo_form.save()
self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c1.id).mapped("quantity_done")), 0)
self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c2.id).mapped("quantity_done")), 1)
details_operation_form = Form(mo.move_raw_ids.filtered(lambda m: m.product_id == c1), view=self.env.ref('stock.view_stock_move_operations'))
with details_operation_form.move_line_ids.edit(0) as ml:
ml.qty_done = 4
ml.lot_id = lot
details_operation_form.save()
action = mo.button_mark_done()
backorder = Form(self.env['mrp.production.backorder'].with_context(**action['context']))
backorder.save().action_backorder()
backorder_mo = mo.procurement_group_id.mrp_production_ids[-1]
self.assertTrue(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
self.assertFalse(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
def test_manual_consumption_backorder_01(self):
"""Test when use_auto_consume_components_lots is set, manual consumption
of the backorder is correctly set.
"""
picking_type = self.env['stock.picking.type'].search([('code', '=', 'mrp_operation')])[0]
picking_type.use_auto_consume_components_lots = True
mo, _, _final, c1, c2 = self.generate_mo('none', 'lot', 'none', qty_final=2)
self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
lot = self.env['stock.lot'].create({
'name': 'lot',
'product_id': c1.id,
'company_id': self.env.company.id,
})
self.env['stock.quant']._update_available_quantity(c1, self.stock_location, 8, lot_id=lot)
self.env['stock.quant']._update_available_quantity(c2, self.stock_location, 2)
mo.action_assign()
mo_form = Form(mo)
mo_form.qty_producing = 1
mo_form.save()
self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c1.id).mapped("quantity_done")), 4)
self.assertEqual(sum(mo.move_raw_ids.filtered(lambda m: m.product_id.id == c2.id).mapped("quantity_done")), 1)
action = mo.button_mark_done()
backorder = Form(self.env['mrp.production.backorder'].with_context(**action['context']))
backorder.save().action_backorder()
backorder_mo = mo.procurement_group_id.mrp_production_ids[-1]
self.assertFalse(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c1).manual_consumption)
self.assertFalse(backorder_mo.move_raw_ids.filtered(lambda m: m.product_id == c2).manual_consumption)
def test_manual_consumption_split_merge_00(self):
"""Test manual consumption is correctly set after split or merge.
"""
# Change 'Units' rounding to 1 (integer only quantities)
self.uom_unit.rounding = 1
# Create a mo for 10 products
mo, _, _, p1, p2 = self.generate_mo('none', 'lot', 'none', qty_final=10)
self.assertTrue(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).manual_consumption)
self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == p2).manual_consumption)
# Split in 3 parts
action = mo.action_split()
wizard = Form(self.env[action['res_model']].with_context(action['context']))
wizard.counter = 3
action = wizard.save().action_split()
for production in mo.procurement_group_id.mrp_production_ids:
self.assertTrue(production.move_raw_ids.filtered(lambda m: m.product_id == p1).manual_consumption)
self.assertFalse(production.move_raw_ids.filtered(lambda m: m.product_id == p2).manual_consumption)
# Merge them back
action = mo.procurement_group_id.mrp_production_ids.action_merge()
mo = self.env[action['res_model']].browse(action['res_id'])
self.assertTrue(mo.move_raw_ids.filtered(lambda m: m.product_id == p1).manual_consumption)
self.assertFalse(mo.move_raw_ids.filtered(lambda m: m.product_id == p2).manual_consumption)