[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:
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user