[FIX] sale_stock_margin: Traceback after reset to quotation avco kit SO

Issue: With margin enabled and avco for stock valuation, after
confirming a SO with a product variant which is a bom kit,
when we try to change the variant, there is a traceback

Steps to reproduce :
1) Install Stock, Accounting, MRP, Sale,
2) Enable Margins in settings

3) Configure a Product Category with costing method AVCO
4) Configure a Product with 2 variants and that product category
5) [Important: KIT] Create 2 BoM, one for each variant and set those
BoM to KIT
6) Create a SO for that product and one variant
7) Confirm the SO, cancel it, and set to quotation
8) Edit the SO and change the variant, save
-> Traceback

Side-Note:
 This issue is due to the fact that we iterate over the stock_moves to
 find the quantity of the BoM, but that stock_move correspond to
 confirming at step 7, when we change the variant at step 8, the stock
 move has not changed, so still contains the previous bom_line_id with
 the quantity, but this doesn't reflect with the new state of the SO
 which is for a different variant.

 For me since the stock move is canceled, it should be taken into
 consideration when computing the average price but I might be wrong,
 it's up to the reviewer to decide if it makes sense

opw-2639093

closes odoo/odoo#77606

X-original-commit: c0d4ed5ac641d339a6cd4e23db9667048d35360d
Signed-off-by: William Henrotin <Whenrow@users.noreply.github.com>
This commit is contained in:
Nathan Marotte (nama)
2021-10-04 09:16:09 +00:00
parent 388ccdfb06
commit b4e11b7dc5
2 changed files with 67 additions and 0 deletions
+2
View File
@@ -57,6 +57,8 @@ class ProductProduct(models.Model):
bom_lines = {line: data for line, data in bom_lines}
value = 0
for move in stock_moves:
if move.state == 'cancel':
continue
bom_line = move.bom_line_id
if bom_line:
bom_line_data = bom_lines[bom_line]
@@ -166,3 +166,68 @@ class TestSaleMrpKitBom(TransactionCase):
cogs_aml = amls.filtered(lambda aml: aml.account_id == self.expense_account)
self.assertAlmostEqual(cogs_aml.debit, 2.53)
self.assertEqual(cogs_aml.credit, 0)
def test_reset_avco_kit(self):
"""
Test a specific use case : One product with 2 variant, each variant has its own BoM with either component_1 or
component_2. Create a SO for one of the variant, confirm, cancel, reset to draft and then change the product of
the SO -> There should be no traceback
"""
component_1 = self.env['product.product'].create({'name': 'compo 1'})
component_2 = self.env['product.product'].create({'name': 'compo 2'})
product_category = self.env['product.category'].create({
'name': 'test avco kit',
'property_cost_method': 'average'
})
attributes = self.env['product.attribute'].create({'name': 'Legs'})
steel_legs = self.env['product.attribute.value'].create({'attribute_id': attributes.id, 'name': 'Steel'})
aluminium_legs = self.env['product.attribute.value'].create(
{'attribute_id': attributes.id, 'name': 'Aluminium'})
product = self.env['product.product'].create({
'name': 'test product',
'categ_id': product_category.id,
'attribute_line_ids': [(0, 0, {
'attribute_id': attributes.id,
'value_ids': [(6, 0, [steel_legs.id, aluminium_legs.id])]
})]
})
product_variant_ids = product.product_variant_ids.search([('id', '!=', product.id)])
product_variant_ids[0].categ_id.property_cost_method = 'average'
product_variant_ids[1].categ_id.property_cost_method = 'average'
# BoM 1 with component_1
self.env['mrp.bom'].create({
'product_id': product_variant_ids[0].id,
'product_tmpl_id': product_variant_ids[0].product_tmpl_id.id,
'product_qty': 1.0,
'consumption': 'flexible',
'type': 'phantom',
'bom_line_ids': [(0, 0, {'product_id': component_1.id, 'product_qty': 1})]
})
# BoM 2 with component_2
self.env['mrp.bom'].create({
'product_id': product_variant_ids[1].id,
'product_tmpl_id': product_variant_ids[1].product_tmpl_id.id,
'product_qty': 1.0,
'consumption': 'flexible',
'type': 'phantom',
'bom_line_ids': [(0, 0, {'product_id': component_2.id, 'product_qty': 1})]
})
partner = self.env['res.partner'].create({'name': 'Testing Man'})
so = self.env['sale.order'].create({
'partner_id': partner.id,
})
# Create the order line
self.env['sale.order.line'].create({
'name': "Order line",
'product_id': product_variant_ids[0].id,
'order_id': so.id,
})
so.action_confirm()
so.action_cancel()
so.action_draft()
with Form(so) as so_form:
with so_form.order_line.edit(0) as order_line_change:
# The actual test, there should be no traceback here
order_line_change.product_id = product_variant_ids[1]