[FIX] sale_mrp: BOM selection in anglosaxon price calculation
We give preference to the bom in the stock moves for the sale order lines If there are changes in BOMs between the stock moves creation and the invoice validation a wrong price will be taken closes odoo/odoo#150506 X-original-commit: 855727eccb4ba9a2af72350b6ab9cc40ba7e50d9 Signed-off-by: William Henrotin (whe) <whe@odoo.com>
This commit is contained in:
committed by
William Henrotin
parent
80fa6d1416
commit
4cbeb0dade
@@ -11,8 +11,12 @@ class AccountMoveLine(models.Model):
|
||||
|
||||
so_line = self.sale_line_ids and self.sale_line_ids[-1] or False
|
||||
if so_line:
|
||||
bom = self.env['mrp.bom']._bom_find(products=so_line.product_id, company_id=so_line.company_id.id, bom_type='phantom')[so_line.product_id]
|
||||
if bom:
|
||||
# We give preference to the bom in the stock moves for the sale order lines
|
||||
# If there are changes in BOMs between the stock moves creation and the
|
||||
# invoice validation a wrong price will be taken
|
||||
boms = so_line.move_ids.filtered(lambda m: m.state != 'cancel').mapped('bom_line_id.bom_id').filtered(lambda b: b.type == 'phantom')
|
||||
if boms:
|
||||
bom = boms[0]
|
||||
is_line_reversing = self.move_id.move_type == 'out_refund'
|
||||
qty_to_invoice = self.product_uom_id._compute_quantity(self.quantity, self.product_id.uom_id)
|
||||
account_moves = so_line.invoice_lines.move_id.filtered(lambda m: m.state == 'posted' and bool(m.reversed_entry_id) == is_line_reversing)
|
||||
|
||||
@@ -1922,6 +1922,145 @@ class TestSaleMrpFlow(TestSaleMrpFlowCommon):
|
||||
self.assertEqual(aml_nokit_expense.debit, 25, "Cost of Good Sold entry missing or mismatching for variant without kit")
|
||||
self.assertEqual(aml_nokit_output.credit, 25, "Cost of Good Sold entry missing or mismatching for variant without kit")
|
||||
|
||||
def test_16_anglo_saxon_variant_price_unit_multi_company(self):
|
||||
"""
|
||||
Test the price unit of the BOM of the stock move is taken
|
||||
Products:
|
||||
Template A
|
||||
variant KIT 1
|
||||
variant KIT 2
|
||||
Business Flow:
|
||||
create SO
|
||||
validate the delivery
|
||||
archive the BOM and create a new one
|
||||
create the invoice
|
||||
post the invoice
|
||||
"""
|
||||
|
||||
# Create environment
|
||||
self.partner = self.env['res.partner'].create({'name': 'Test Partner'})
|
||||
self.category = self.env.ref('product.product_category_1').copy({'name': 'Test category', 'property_valuation': 'real_time', 'property_cost_method': 'fifo'})
|
||||
account_receiv = self.env['account.account'].create({'name': 'Receivable', 'code': 'RCV00', 'account_type': 'asset_receivable', 'reconcile': True})
|
||||
account_income = self.env['account.account'].create({'name': 'Income', 'code': 'INC00', 'account_type': 'asset_current', 'reconcile': True})
|
||||
account_expense = self.env['account.account'].create({'name': 'Expense', 'code': 'EXP00', 'account_type': 'liability_current', 'reconcile': True})
|
||||
account_output = self.env['account.account'].create({'name': 'Output', 'code': 'OUT00', 'account_type': 'liability_current', 'reconcile': True})
|
||||
account_valuation = self.env['account.account'].create({'name': 'Valuation', 'code': 'STV00', 'account_type': 'asset_receivable', 'reconcile': True})
|
||||
self.stock_location = self.company_data['default_warehouse'].lot_stock_id
|
||||
self.partner.property_account_receivable_id = account_receiv
|
||||
self.category.property_account_income_categ_id = account_income
|
||||
self.category.property_account_expense_categ_id = account_expense
|
||||
self.category.property_stock_account_input_categ_id = account_income
|
||||
self.category.property_stock_account_output_categ_id = account_output
|
||||
self.category.property_stock_valuation_account_id = account_valuation
|
||||
|
||||
# Create variant attributes
|
||||
self.prod_att_test = self.env['product.attribute'].create({'name': 'test'})
|
||||
self.prod_attr_KIT_A = self.env['product.attribute.value'].create({'name': 'KIT A', 'attribute_id': self.prod_att_test.id, 'sequence': 1})
|
||||
|
||||
# Create the template
|
||||
self.product_template = self.env['product.template'].create({
|
||||
'name': 'Template A',
|
||||
'type': 'product',
|
||||
'uom_id': self.uom_unit.id,
|
||||
'invoice_policy': 'delivery',
|
||||
'categ_id': self.category.id,
|
||||
'attribute_line_ids': [(0, 0, {
|
||||
'attribute_id': self.prod_att_test.id,
|
||||
'value_ids': [(6, 0, [self.prod_attr_KIT_A.id])]
|
||||
})]
|
||||
})
|
||||
|
||||
# Create another variant
|
||||
self.pt_attr_KIT_A = self.product_template.attribute_line_ids[0].product_template_value_ids[0]
|
||||
self.variant_KIT_A = self.product_template._get_variant_for_combination(self.pt_attr_KIT_A)
|
||||
# Assign a cost to the NOKIT variant
|
||||
self.variant_KIT_A.write({'standard_price': 25})
|
||||
|
||||
# Create the components
|
||||
self.comp_kit_a = self.env['product.product'].create({
|
||||
'name': 'Component Kit A',
|
||||
'type': 'product',
|
||||
'uom_id': self.uom_unit.id,
|
||||
'categ_id': self.category.id,
|
||||
'standard_price': 20
|
||||
})
|
||||
self.comp_kit_b = self.env['product.product'].create({
|
||||
'name': 'Component Kit B',
|
||||
'type': 'product',
|
||||
'uom_id': self.uom_unit.id,
|
||||
'categ_id': self.category.id,
|
||||
'standard_price': 10
|
||||
})
|
||||
|
||||
# Create the bom
|
||||
bom = self.env['mrp.bom'].create({
|
||||
'product_tmpl_id': self.product_template.id,
|
||||
'product_id': self.variant_KIT_A.id,
|
||||
'product_qty': 1.0,
|
||||
'type': 'phantom',
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
self.env['mrp.bom.line'].create({
|
||||
'product_id': self.comp_kit_a.id,
|
||||
'product_qty': 1.0,
|
||||
'company_id': self.env.company.id,
|
||||
'bom_id': bom.id
|
||||
})
|
||||
|
||||
# Create the quants
|
||||
self.env['stock.quant']._update_available_quantity(self.comp_kit_a, self.stock_location, 2)
|
||||
self.env['stock.quant']._update_available_quantity(self.comp_kit_b, self.stock_location, 1)
|
||||
|
||||
# Create the sale order
|
||||
so_vals = {
|
||||
'partner_id': self.partner.id,
|
||||
'partner_invoice_id': self.partner.id,
|
||||
'partner_shipping_id': self.partner.id,
|
||||
'order_line': [(0, 0, {
|
||||
'name': self.variant_KIT_A.name,
|
||||
'product_id': self.variant_KIT_A.id,
|
||||
'product_uom_qty': 1,
|
||||
'product_uom': self.uom_unit.id,
|
||||
'price_unit': 50
|
||||
})],
|
||||
'company_id': self.env.company.id,
|
||||
}
|
||||
so = self.env['sale.order'].create(so_vals)
|
||||
# Validate the sale order
|
||||
so.action_confirm()
|
||||
# Deliver the products
|
||||
pick = so.picking_ids
|
||||
pick.button_validate()
|
||||
# archive bOM and update it
|
||||
bom.active = False
|
||||
bom_updated = self.env['mrp.bom'].create({
|
||||
'product_tmpl_id': self.product_template.id,
|
||||
'product_id': self.variant_KIT_A.id,
|
||||
'product_qty': 1.0,
|
||||
'type': 'phantom',
|
||||
'company_id': self.env.company.id,
|
||||
})
|
||||
self.env['mrp.bom.line'].create({
|
||||
'product_id': self.comp_kit_b.id,
|
||||
'product_qty': 1.0,
|
||||
'company_id': self.env.company.id,
|
||||
'bom_id': bom_updated.id
|
||||
})
|
||||
|
||||
# Create the invoice
|
||||
so._create_invoices()
|
||||
# Validate the invoice
|
||||
invoice = so.invoice_ids
|
||||
invoice.action_post()
|
||||
|
||||
amls = invoice.line_ids
|
||||
aml_nokit_expense = amls.filtered(lambda l: l.display_type == 'cogs' and l.debit > 0 and l.product_id == self.variant_KIT_A)
|
||||
aml_nokit_output = amls.filtered(lambda l: l.display_type == 'cogs' and l.credit > 0 and l.product_id == self.variant_KIT_A)
|
||||
|
||||
# Check that the Cost of Goods Sold for variant NOKIT is equal to the cost of the first BOM
|
||||
self.assertEqual(aml_nokit_expense.debit, 20, "Cost of Good Sold entry missing or mismatching for variant without kit")
|
||||
self.assertEqual(aml_nokit_output.credit, 20, "Cost of Good Sold entry missing or mismatching for variant without kit")
|
||||
|
||||
def test_reconfirm_cancelled_kit(self):
|
||||
so = self.env['sale.order'].create({
|
||||
'partner_id': self.env['res.partner'].create({'name': 'Test Partner'}).id,
|
||||
|
||||
Reference in New Issue
Block a user